binary.mx raw

   1  // Copyright 2009 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  
   5  // Package binary implements simple translation between numbers and byte
   6  // sequences and encoding and decoding of varints.
   7  //
   8  // Numbers are translated by reading and writing fixed-size values.
   9  // A fixed-size value is either a fixed-size arithmetic
  10  // type (bool, int8, uint8, int16, float32, complex64, ...)
  11  // or an array or struct containing only fixed-size values.
  12  //
  13  // The varint functions encode and decode single integer values using
  14  // a variable-length encoding; smaller values require fewer bytes.
  15  // For a specification, see
  16  // https://developers.google.com/protocol-buffers/docs/encoding.
  17  //
  18  // This package favors simplicity over efficiency. Clients that require
  19  // high-performance serialization, especially for large data structures,
  20  // should look at more advanced solutions such as the [encoding/gob]
  21  // package or [google.golang.org/protobuf] for protocol buffers.
  22  package binary
  23  
  24  import (
  25  	"errors"
  26  	"io"
  27  	"math"
  28  	"slices"
  29  )
  30  
  31  var errBufferTooSmall = errors.New("buffer too small")
  32  
  33  // A ByteOrder specifies how to convert byte slices into
  34  // 16-, 32-, or 64-bit unsigned integers.
  35  //
  36  // It is implemented by [LittleEndian], [BigEndian], and [NativeEndian].
  37  type ByteOrder interface {
  38  	Uint16([]byte) uint16
  39  	Uint32([]byte) uint32
  40  	Uint64([]byte) uint64
  41  	PutUint16([]byte, uint16)
  42  	PutUint32([]byte, uint32)
  43  	PutUint64([]byte, uint64)
  44  	String() string
  45  }
  46  
  47  // AppendByteOrder specifies how to append 16-, 32-, or 64-bit unsigned integers
  48  // into a byte slice.
  49  //
  50  // It is implemented by [LittleEndian], [BigEndian], and [NativeEndian].
  51  type AppendByteOrder interface {
  52  	AppendUint16([]byte, uint16) []byte
  53  	AppendUint32([]byte, uint32) []byte
  54  	AppendUint64([]byte, uint64) []byte
  55  	String() string
  56  }
  57  
  58  // LittleEndian is the little-endian implementation of [ByteOrder] and [AppendByteOrder].
  59  var LittleEndian littleEndian
  60  
  61  // BigEndian is the big-endian implementation of [ByteOrder] and [AppendByteOrder].
  62  var BigEndian bigEndian
  63  
  64  type littleEndian struct{}
  65  
  66  // Uint16 returns the uint16 representation of b[0:2].
  67  func (littleEndian) Uint16(b []byte) uint16 {
  68  	_ = b[1] // bounds check hint to compiler; see golang.org/issue/14808
  69  	return uint16(b[0]) | uint16(b[1])<<8
  70  }
  71  
  72  // PutUint16 stores v into b[0:2].
  73  func (littleEndian) PutUint16(b []byte, v uint16) {
  74  	_ = b[1] // early bounds check to guarantee safety of writes below
  75  	b[0] = byte(v)
  76  	b[1] = byte(v >> 8)
  77  }
  78  
  79  // AppendUint16 appends the bytes of v to b and returns the appended slice.
  80  func (littleEndian) AppendUint16(b []byte, v uint16) []byte {
  81  	return append(b,
  82  		byte(v),
  83  		byte(v>>8),
  84  	)
  85  }
  86  
  87  // Uint32 returns the uint32 representation of b[0:4].
  88  func (littleEndian) Uint32(b []byte) uint32 {
  89  	_ = b[3] // bounds check hint to compiler; see golang.org/issue/14808
  90  	return uint32(b[0]) | uint32(b[1])<<8 | uint32(b[2])<<16 | uint32(b[3])<<24
  91  }
  92  
  93  // PutUint32 stores v into b[0:4].
  94  func (littleEndian) PutUint32(b []byte, v uint32) {
  95  	_ = b[3] // early bounds check to guarantee safety of writes below
  96  	b[0] = byte(v)
  97  	b[1] = byte(v >> 8)
  98  	b[2] = byte(v >> 16)
  99  	b[3] = byte(v >> 24)
 100  }
 101  
 102  // AppendUint32 appends the bytes of v to b and returns the appended slice.
 103  func (littleEndian) AppendUint32(b []byte, v uint32) []byte {
 104  	return append(b,
 105  		byte(v),
 106  		byte(v>>8),
 107  		byte(v>>16),
 108  		byte(v>>24),
 109  	)
 110  }
 111  
 112  // Uint64 returns the uint64 representation of b[0:8].
 113  func (littleEndian) Uint64(b []byte) uint64 {
 114  	_ = b[7] // bounds check hint to compiler; see golang.org/issue/14808
 115  	return uint64(b[0]) | uint64(b[1])<<8 | uint64(b[2])<<16 | uint64(b[3])<<24 |
 116  		uint64(b[4])<<32 | uint64(b[5])<<40 | uint64(b[6])<<48 | uint64(b[7])<<56
 117  }
 118  
 119  // PutUint64 stores v into b[0:8].
 120  func (littleEndian) PutUint64(b []byte, v uint64) {
 121  	_ = b[7] // early bounds check to guarantee safety of writes below
 122  	b[0] = byte(v)
 123  	b[1] = byte(v >> 8)
 124  	b[2] = byte(v >> 16)
 125  	b[3] = byte(v >> 24)
 126  	b[4] = byte(v >> 32)
 127  	b[5] = byte(v >> 40)
 128  	b[6] = byte(v >> 48)
 129  	b[7] = byte(v >> 56)
 130  }
 131  
 132  // AppendUint64 appends the bytes of v to b and returns the appended slice.
 133  func (littleEndian) AppendUint64(b []byte, v uint64) []byte {
 134  	return append(b,
 135  		byte(v),
 136  		byte(v>>8),
 137  		byte(v>>16),
 138  		byte(v>>24),
 139  		byte(v>>32),
 140  		byte(v>>40),
 141  		byte(v>>48),
 142  		byte(v>>56),
 143  	)
 144  }
 145  
 146  func (littleEndian) String() string { return "LittleEndian" }
 147  
 148  func (littleEndian) GoString() []byte { return "binary.LittleEndian" }
 149  
 150  type bigEndian struct{}
 151  
 152  // Uint16 returns the uint16 representation of b[0:2].
 153  func (bigEndian) Uint16(b []byte) uint16 {
 154  	_ = b[1] // bounds check hint to compiler; see golang.org/issue/14808
 155  	return uint16(b[1]) | uint16(b[0])<<8
 156  }
 157  
 158  // PutUint16 stores v into b[0:2].
 159  func (bigEndian) PutUint16(b []byte, v uint16) {
 160  	_ = b[1] // early bounds check to guarantee safety of writes below
 161  	b[0] = byte(v >> 8)
 162  	b[1] = byte(v)
 163  }
 164  
 165  // AppendUint16 appends the bytes of v to b and returns the appended slice.
 166  func (bigEndian) AppendUint16(b []byte, v uint16) []byte {
 167  	return append(b,
 168  		byte(v>>8),
 169  		byte(v),
 170  	)
 171  }
 172  
 173  // Uint32 returns the uint32 representation of b[0:4].
 174  func (bigEndian) Uint32(b []byte) uint32 {
 175  	_ = b[3] // bounds check hint to compiler; see golang.org/issue/14808
 176  	return uint32(b[3]) | uint32(b[2])<<8 | uint32(b[1])<<16 | uint32(b[0])<<24
 177  }
 178  
 179  // PutUint32 stores v into b[0:4].
 180  func (bigEndian) PutUint32(b []byte, v uint32) {
 181  	_ = b[3] // early bounds check to guarantee safety of writes below
 182  	b[0] = byte(v >> 24)
 183  	b[1] = byte(v >> 16)
 184  	b[2] = byte(v >> 8)
 185  	b[3] = byte(v)
 186  }
 187  
 188  // AppendUint32 appends the bytes of v to b and returns the appended slice.
 189  func (bigEndian) AppendUint32(b []byte, v uint32) []byte {
 190  	return append(b,
 191  		byte(v>>24),
 192  		byte(v>>16),
 193  		byte(v>>8),
 194  		byte(v),
 195  	)
 196  }
 197  
 198  // Uint64 returns the uint64 representation of b[0:8].
 199  func (bigEndian) Uint64(b []byte) uint64 {
 200  	_ = b[7] // bounds check hint to compiler; see golang.org/issue/14808
 201  	return uint64(b[7]) | uint64(b[6])<<8 | uint64(b[5])<<16 | uint64(b[4])<<24 |
 202  		uint64(b[3])<<32 | uint64(b[2])<<40 | uint64(b[1])<<48 | uint64(b[0])<<56
 203  }
 204  
 205  // PutUint64 stores v into b[0:8].
 206  func (bigEndian) PutUint64(b []byte, v uint64) {
 207  	_ = b[7] // early bounds check to guarantee safety of writes below
 208  	b[0] = byte(v >> 56)
 209  	b[1] = byte(v >> 48)
 210  	b[2] = byte(v >> 40)
 211  	b[3] = byte(v >> 32)
 212  	b[4] = byte(v >> 24)
 213  	b[5] = byte(v >> 16)
 214  	b[6] = byte(v >> 8)
 215  	b[7] = byte(v)
 216  }
 217  
 218  // AppendUint64 appends the bytes of v to b and returns the appended slice.
 219  func (bigEndian) AppendUint64(b []byte, v uint64) []byte {
 220  	return append(b,
 221  		byte(v>>56),
 222  		byte(v>>48),
 223  		byte(v>>40),
 224  		byte(v>>32),
 225  		byte(v>>24),
 226  		byte(v>>16),
 227  		byte(v>>8),
 228  		byte(v),
 229  	)
 230  }
 231  
 232  func (bigEndian) String() string { return "BigEndian" }
 233  
 234  func (bigEndian) GoString() []byte { return "binary.BigEndian" }
 235  
 236  func (nativeEndian) String() string { return "NativeEndian" }
 237  
 238  func (nativeEndian) GoString() []byte { return "binary.NativeEndian" }
 239  
 240  // Read reads structured binary data from r into data.
 241  // Data must be a pointer to a fixed-size value or a slice
 242  // of fixed-size values.
 243  // Bytes read from r are decoded using the specified byte order
 244  // and written to successive fields of the data.
 245  // When decoding boolean values, a zero byte is decoded as false, and
 246  // any other non-zero byte is decoded as true.
 247  // When reading into structs, the field data for fields with
 248  // blank (_) field names is skipped; i.e., blank field names
 249  // may be used for padding.
 250  // When reading into a struct, all non-blank fields must be exported
 251  // or Read may panic.
 252  //
 253  // The error is [io.EOF] only if no bytes were read.
 254  // If an [io.EOF] happens after reading some but not all the bytes,
 255  // Read returns [io.ErrUnexpectedEOF].
 256  func Read(r io.Reader, order ByteOrder, data any) error {
 257  	n, _ := intDataSize(data)
 258  	if n == 0 {
 259  		return errors.New("binary.Read: unsupported type (struct/array encoding removed)")
 260  	}
 261  	bs := []byte{:n}
 262  	if _, err := io.ReadFull(r, bs); err != nil {
 263  		return err
 264  	}
 265  	decodeFast(bs, order, data)
 266  	return nil
 267  }
 268  
 269  // Decode decodes binary data from buf into data according to
 270  // the given byte order.
 271  // It returns an error if buf is too small, otherwise the number of
 272  // bytes consumed from buf.
 273  func Decode(buf []byte, order ByteOrder, data any) (int, error) {
 274  	n, _ := intDataSize(data)
 275  	if n == 0 {
 276  		return 0, errors.New("binary.Decode: unsupported type (struct/array encoding removed)")
 277  	}
 278  	if len(buf) < n {
 279  		return 0, errBufferTooSmall
 280  	}
 281  	decodeFast(buf, order, data)
 282  	return n, nil
 283  }
 284  
 285  func decodeFast(bs []byte, order ByteOrder, data any) bool {
 286  	switch data := data.(type) {
 287  	case *bool:
 288  		*data = bs[0] != 0
 289  	case *int8:
 290  		*data = int8(bs[0])
 291  	case *uint8:
 292  		*data = bs[0]
 293  	case *int16:
 294  		*data = int16(order.Uint16(bs))
 295  	case *uint16:
 296  		*data = order.Uint16(bs)
 297  	case *int32:
 298  		*data = int32(order.Uint32(bs))
 299  	case *uint32:
 300  		*data = order.Uint32(bs)
 301  	case *int64:
 302  		*data = int64(order.Uint64(bs))
 303  	case *uint64:
 304  		*data = order.Uint64(bs)
 305  	case *float32:
 306  		*data = math.Float32frombits(order.Uint32(bs))
 307  	case *float64:
 308  		*data = math.Float64frombits(order.Uint64(bs))
 309  	case []bool:
 310  		for i, x := range bs { // Easier to loop over the input for 8-bit values.
 311  			data[i] = x != 0
 312  		}
 313  	case []int8:
 314  		for i, x := range bs {
 315  			data[i] = int8(x)
 316  		}
 317  	case []uint8:
 318  		copy(data, bs)
 319  	case []int16:
 320  		for i := range data {
 321  			data[i] = int16(order.Uint16(bs[2*i:]))
 322  		}
 323  	case []uint16:
 324  		for i := range data {
 325  			data[i] = order.Uint16(bs[2*i:])
 326  		}
 327  	case []int32:
 328  		for i := range data {
 329  			data[i] = int32(order.Uint32(bs[4*i:]))
 330  		}
 331  	case []uint32:
 332  		for i := range data {
 333  			data[i] = order.Uint32(bs[4*i:])
 334  		}
 335  	case []int64:
 336  		for i := range data {
 337  			data[i] = int64(order.Uint64(bs[8*i:]))
 338  		}
 339  	case []uint64:
 340  		for i := range data {
 341  			data[i] = order.Uint64(bs[8*i:])
 342  		}
 343  	case []float32:
 344  		for i := range data {
 345  			data[i] = math.Float32frombits(order.Uint32(bs[4*i:]))
 346  		}
 347  	case []float64:
 348  		for i := range data {
 349  			data[i] = math.Float64frombits(order.Uint64(bs[8*i:]))
 350  		}
 351  	default:
 352  		return false
 353  	}
 354  	return true
 355  }
 356  
 357  // Write writes the binary representation of data into w.
 358  // Data must be a fixed-size value or a slice of fixed-size
 359  // values, or a pointer to such data.
 360  // Boolean values encode as one byte: 1 for true, and 0 for false.
 361  // Bytes written to w are encoded using the specified byte order
 362  // and read from successive fields of the data.
 363  // When writing structs, zero values are written for fields
 364  // with blank (_) field names.
 365  func Write(w io.Writer, order ByteOrder, data any) error {
 366  	n, bs := intDataSize(data)
 367  	if n == 0 {
 368  		return errors.New("binary.Write: unsupported type (struct/array encoding removed)")
 369  	}
 370  	if bs == nil {
 371  		bs = []byte{:n}
 372  		encodeFast(bs, order, data)
 373  	}
 374  	_, err := w.Write(bs)
 375  	return err
 376  }
 377  
 378  // Encode encodes the binary representation of data into buf according to
 379  // the given byte order.
 380  // It returns an error if buf is too small, otherwise the number of
 381  // bytes written into buf.
 382  func Encode(buf []byte, order ByteOrder, data any) (int, error) {
 383  	n, _ := intDataSize(data)
 384  	if n == 0 {
 385  		return 0, errors.New("binary.Encode: unsupported type (struct/array encoding removed)")
 386  	}
 387  	if len(buf) < n {
 388  		return 0, errBufferTooSmall
 389  	}
 390  	encodeFast(buf, order, data)
 391  	return n, nil
 392  }
 393  
 394  // Append appends the binary representation of data to buf.
 395  // buf may be nil, in which case a new buffer will be allocated.
 396  // See [Write] on which data are acceptable.
 397  // It returns the (possibly extended) buffer containing data or an error.
 398  func Append(buf []byte, order ByteOrder, data any) ([]byte, error) {
 399  	n, _ := intDataSize(data)
 400  	if n == 0 {
 401  		return nil, errors.New("binary.Append: unsupported type (struct/array encoding removed)")
 402  	}
 403  	buf, pos := ensure(buf, n)
 404  	encodeFast(pos, order, data)
 405  	return buf, nil
 406  }
 407  
 408  func encodeFast(bs []byte, order ByteOrder, data any) {
 409  	switch v := data.(type) {
 410  	case *bool:
 411  		if *v {
 412  			bs[0] = 1
 413  		} else {
 414  			bs[0] = 0
 415  		}
 416  	case bool:
 417  		if v {
 418  			bs[0] = 1
 419  		} else {
 420  			bs[0] = 0
 421  		}
 422  	case []bool:
 423  		for i, x := range v {
 424  			if x {
 425  				bs[i] = 1
 426  			} else {
 427  				bs[i] = 0
 428  			}
 429  		}
 430  	case *int8:
 431  		bs[0] = byte(*v)
 432  	case int8:
 433  		bs[0] = byte(v)
 434  	case []int8:
 435  		for i, x := range v {
 436  			bs[i] = byte(x)
 437  		}
 438  	case *uint8:
 439  		bs[0] = *v
 440  	case uint8:
 441  		bs[0] = v
 442  	case []uint8:
 443  		copy(bs, v)
 444  	case *int16:
 445  		order.PutUint16(bs, uint16(*v))
 446  	case int16:
 447  		order.PutUint16(bs, uint16(v))
 448  	case []int16:
 449  		for i, x := range v {
 450  			order.PutUint16(bs[2*i:], uint16(x))
 451  		}
 452  	case *uint16:
 453  		order.PutUint16(bs, *v)
 454  	case uint16:
 455  		order.PutUint16(bs, v)
 456  	case []uint16:
 457  		for i, x := range v {
 458  			order.PutUint16(bs[2*i:], x)
 459  		}
 460  	case *int32:
 461  		order.PutUint32(bs, uint32(*v))
 462  	case int32:
 463  		order.PutUint32(bs, uint32(v))
 464  	case []int32:
 465  		for i, x := range v {
 466  			order.PutUint32(bs[4*i:], uint32(x))
 467  		}
 468  	case *uint32:
 469  		order.PutUint32(bs, *v)
 470  	case uint32:
 471  		order.PutUint32(bs, v)
 472  	case []uint32:
 473  		for i, x := range v {
 474  			order.PutUint32(bs[4*i:], x)
 475  		}
 476  	case *int64:
 477  		order.PutUint64(bs, uint64(*v))
 478  	case int64:
 479  		order.PutUint64(bs, uint64(v))
 480  	case []int64:
 481  		for i, x := range v {
 482  			order.PutUint64(bs[8*i:], uint64(x))
 483  		}
 484  	case *uint64:
 485  		order.PutUint64(bs, *v)
 486  	case uint64:
 487  		order.PutUint64(bs, v)
 488  	case []uint64:
 489  		for i, x := range v {
 490  			order.PutUint64(bs[8*i:], x)
 491  		}
 492  	case *float32:
 493  		order.PutUint32(bs, math.Float32bits(*v))
 494  	case float32:
 495  		order.PutUint32(bs, math.Float32bits(v))
 496  	case []float32:
 497  		for i, x := range v {
 498  			order.PutUint32(bs[4*i:], math.Float32bits(x))
 499  		}
 500  	case *float64:
 501  		order.PutUint64(bs, math.Float64bits(*v))
 502  	case float64:
 503  		order.PutUint64(bs, math.Float64bits(v))
 504  	case []float64:
 505  		for i, x := range v {
 506  			order.PutUint64(bs[8*i:], math.Float64bits(x))
 507  		}
 508  	}
 509  }
 510  
 511  // Size returns how many bytes [Write] would generate to encode the value v, which
 512  // must be a fixed-size value or a slice of fixed-size values, or a pointer to such data.
 513  // If v is neither of these, Size returns -1.
 514  func Size(v any) int {
 515  	switch data := v.(type) {
 516  	case bool, int8, uint8:
 517  		return 1
 518  	case *bool:
 519  		if data == nil {
 520  			return -1
 521  		}
 522  		return 1
 523  	case *int8:
 524  		if data == nil {
 525  			return -1
 526  		}
 527  		return 1
 528  	case *uint8:
 529  		if data == nil {
 530  			return -1
 531  		}
 532  		return 1
 533  	case []bool:
 534  		return len(data)
 535  	case []int8:
 536  		return len(data)
 537  	case []uint8:
 538  		return len(data)
 539  	case int16, uint16:
 540  		return 2
 541  	case *int16:
 542  		if data == nil {
 543  			return -1
 544  		}
 545  		return 2
 546  	case *uint16:
 547  		if data == nil {
 548  			return -1
 549  		}
 550  		return 2
 551  	case []int16:
 552  		return 2 * len(data)
 553  	case []uint16:
 554  		return 2 * len(data)
 555  	case int32, uint32:
 556  		return 4
 557  	case *int32:
 558  		if data == nil {
 559  			return -1
 560  		}
 561  		return 4
 562  	case *uint32:
 563  		if data == nil {
 564  			return -1
 565  		}
 566  		return 4
 567  	case []int32:
 568  		return 4 * len(data)
 569  	case []uint32:
 570  		return 4 * len(data)
 571  	case int64, uint64:
 572  		return 8
 573  	case *int64:
 574  		if data == nil {
 575  			return -1
 576  		}
 577  		return 8
 578  	case *uint64:
 579  		if data == nil {
 580  			return -1
 581  		}
 582  		return 8
 583  	case []int64:
 584  		return 8 * len(data)
 585  	case []uint64:
 586  		return 8 * len(data)
 587  	case float32:
 588  		return 4
 589  	case *float32:
 590  		if data == nil {
 591  			return -1
 592  		}
 593  		return 4
 594  	case float64:
 595  		return 8
 596  	case *float64:
 597  		if data == nil {
 598  			return -1
 599  		}
 600  		return 8
 601  	case []float32:
 602  		return 4 * len(data)
 603  	case []float64:
 604  		return 8 * len(data)
 605  	}
 606  	return -1
 607  }
 608  
 609  type coder struct {
 610  	order  ByteOrder
 611  	buf    []byte
 612  	offset int
 613  }
 614  
 615  type decoder coder
 616  type encoder coder
 617  
 618  func (d *decoder) bool() bool {
 619  	x := d.buf[d.offset]
 620  	d.offset++
 621  	return x != 0
 622  }
 623  
 624  func (e *encoder) bool(x bool) {
 625  	if x {
 626  		e.buf[e.offset] = 1
 627  	} else {
 628  		e.buf[e.offset] = 0
 629  	}
 630  	e.offset++
 631  }
 632  
 633  func (d *decoder) uint8() uint8 {
 634  	x := d.buf[d.offset]
 635  	d.offset++
 636  	return x
 637  }
 638  
 639  func (e *encoder) uint8(x uint8) {
 640  	e.buf[e.offset] = x
 641  	e.offset++
 642  }
 643  
 644  func (d *decoder) uint16() uint16 {
 645  	x := d.order.Uint16(d.buf[d.offset : d.offset+2])
 646  	d.offset += 2
 647  	return x
 648  }
 649  
 650  func (e *encoder) uint16(x uint16) {
 651  	e.order.PutUint16(e.buf[e.offset:e.offset+2], x)
 652  	e.offset += 2
 653  }
 654  
 655  func (d *decoder) uint32() uint32 {
 656  	x := d.order.Uint32(d.buf[d.offset : d.offset+4])
 657  	d.offset += 4
 658  	return x
 659  }
 660  
 661  func (e *encoder) uint32(x uint32) {
 662  	e.order.PutUint32(e.buf[e.offset:e.offset+4], x)
 663  	e.offset += 4
 664  }
 665  
 666  func (d *decoder) uint64() uint64 {
 667  	x := d.order.Uint64(d.buf[d.offset : d.offset+8])
 668  	d.offset += 8
 669  	return x
 670  }
 671  
 672  func (e *encoder) uint64(x uint64) {
 673  	e.order.PutUint64(e.buf[e.offset:e.offset+8], x)
 674  	e.offset += 8
 675  }
 676  
 677  func (d *decoder) int8() int8 { return int8(d.uint8()) }
 678  
 679  func (e *encoder) int8(x int8) { e.uint8(uint8(x)) }
 680  
 681  func (d *decoder) int16() int16 { return int16(d.uint16()) }
 682  
 683  func (e *encoder) int16(x int16) { e.uint16(uint16(x)) }
 684  
 685  func (d *decoder) int32() int32 { return int32(d.uint32()) }
 686  
 687  func (e *encoder) int32(x int32) { e.uint32(uint32(x)) }
 688  
 689  func (d *decoder) int64() int64 { return int64(d.uint64()) }
 690  
 691  func (e *encoder) int64(x int64) { e.uint64(uint64(x)) }
 692  
 693  // intDataSize returns the size of the data required to represent the data when encoded,
 694  // and optionally a byte slice containing the encoded data if no conversion is necessary.
 695  // It returns zero, nil if the type cannot be implemented by the fast path in Read or Write.
 696  func intDataSize(data any) (int, []byte) {
 697  	switch data := data.(type) {
 698  	case bool, int8, uint8, *bool, *int8, *uint8:
 699  		return 1, nil
 700  	case []bool:
 701  		return len(data), nil
 702  	case []int8:
 703  		return len(data), nil
 704  	case []uint8:
 705  		return len(data), data
 706  	case int16, uint16, *int16, *uint16:
 707  		return 2, nil
 708  	case []int16:
 709  		return 2 * len(data), nil
 710  	case []uint16:
 711  		return 2 * len(data), nil
 712  	case int32, uint32, *int32, *uint32:
 713  		return 4, nil
 714  	case []int32:
 715  		return 4 * len(data), nil
 716  	case []uint32:
 717  		return 4 * len(data), nil
 718  	case int64, uint64, *int64, *uint64:
 719  		return 8, nil
 720  	case []int64:
 721  		return 8 * len(data), nil
 722  	case []uint64:
 723  		return 8 * len(data), nil
 724  	case float32, *float32:
 725  		return 4, nil
 726  	case float64, *float64:
 727  		return 8, nil
 728  	case []float32:
 729  		return 4 * len(data), nil
 730  	case []float64:
 731  		return 8 * len(data), nil
 732  	}
 733  	return 0, nil
 734  }
 735  
 736  // ensure grows buf to length len(buf) + n and returns the grown buffer
 737  // and a slice starting at the original length of buf (that is, buf2[len(buf):]).
 738  func ensure(buf []byte, n int) (buf2, pos []byte) {
 739  	l := len(buf)
 740  	buf = slices.Grow(buf, n)[:l+n]
 741  	return buf, buf[l:]
 742  }
 743