]> Cypherpunks repositories - gostls13.git/commitdiff
all: rewrite internal/saferio.SliceCap using generics and add func SliceCapWithSize
authorJes Cok <xigua67damn@gmail.com>
Wed, 30 Aug 2023 04:23:55 +0000 (04:23 +0000)
committerGopher Robot <gobot@golang.org>
Thu, 31 Aug 2023 00:34:05 +0000 (00:34 +0000)
Change-Id: I265173bf2722796c4be545c968efef3a1a6f7a7d
GitHub-Last-Rev: 04d95cdd615f906167545f246f707e1440c39374
GitHub-Pull-Request: golang/go#62365
Reviewed-on: https://go-review.googlesource.com/c/go/+/524257
LUCI-TryBot-Result: Go LUCI <golang-scoped@luci-project-accounts.iam.gserviceaccount.com>
Auto-Submit: Ian Lance Taylor <iant@google.com>
Reviewed-by: Russ Cox <rsc@golang.org>
Reviewed-by: Ian Lance Taylor <iant@google.com>
src/debug/elf/file.go
src/debug/macho/fat.go
src/debug/macho/file.go
src/debug/pe/symbol.go
src/encoding/gob/decode.go
src/internal/saferio/io.go
src/internal/saferio/io_test.go
src/internal/xcoff/file.go

index 9416ddaefb95b9f116dff99400e91eb522350265..87773541f0b6c244f3665b1fbf11ada7cdb8f37a 100644 (file)
@@ -498,7 +498,7 @@ func NewFile(r io.ReaderAt) (*File, error) {
        }
 
        // Read section headers
-       c := saferio.SliceCap((*Section)(nil), uint64(shnum))
+       c := saferio.SliceCap[Section](uint64(shnum))
        if c < 0 {
                return nil, &FormatError{0, "too many sections", shnum}
        }
index 679cefb3139e6a943c72017510344bc46d3fc17f..cc2134626ffa47895d927a7d2d520f073f32146c 100644 (file)
@@ -86,7 +86,7 @@ func NewFatFile(r io.ReaderAt) (*FatFile, error) {
 
        // Following the fat_header comes narch fat_arch structs that index
        // Mach-O images further in the file.
-       c := saferio.SliceCap((*FatArch)(nil), uint64(narch))
+       c := saferio.SliceCap[FatArch](uint64(narch))
        if c < 0 {
                return nil, &FormatError{offset, "too many images", nil}
        }
index 7cba3398fbca07a63f71e29ba61782dc0a4f9efb..74a4da4da68c45445b1be76346fc0e375d68a66e 100644 (file)
@@ -263,7 +263,7 @@ func NewFile(r io.ReaderAt) (*File, error) {
        if err != nil {
                return nil, err
        }
-       c := saferio.SliceCap((*Load)(nil), uint64(f.Ncmd))
+       c := saferio.SliceCap[Load](uint64(f.Ncmd))
        if c < 0 {
                return nil, &FormatError{offset, "too many load commands", nil}
        }
@@ -472,7 +472,7 @@ func NewFile(r io.ReaderAt) (*File, error) {
 
 func (f *File) parseSymtab(symdat, strtab, cmddat []byte, hdr *SymtabCmd, offset int64) (*Symtab, error) {
        bo := f.ByteOrder
-       c := saferio.SliceCap((*Symbol)(nil), uint64(hdr.Nsyms))
+       c := saferio.SliceCap[Symbol](uint64(hdr.Nsyms))
        if c < 0 {
                return nil, &FormatError{offset, "too many symbols", nil}
        }
index c33a4fc87515af5a6dd1b85f1cb3a632a983f915..2e03af76bd24ab785e6aa3fc95ff4cfb9bdd5b93 100644 (file)
@@ -59,7 +59,7 @@ func readCOFFSymbols(fh *FileHeader, r io.ReadSeeker) ([]COFFSymbol, error) {
        if err != nil {
                return nil, fmt.Errorf("fail to seek to symbol table: %v", err)
        }
-       c := saferio.SliceCap((*COFFSymbol)(nil), uint64(fh.NumberOfSymbols))
+       c := saferio.SliceCap[COFFSymbol](uint64(fh.NumberOfSymbols))
        if c < 0 {
                return nil, errors.New("too many symbols; file may be corrupt")
        }
index 46657183f2c469f220d587a1e4bcaa8780117138..868893312e9cff0b452da8f3d8b9ada92f71ab6a 100644 (file)
@@ -370,7 +370,7 @@ func decUint8Slice(i *decInstr, state *decoderState, value reflect.Value) {
                errorf("bad %s slice length: %d", value.Type(), n)
        }
        if value.Cap() < n {
-               safe := saferio.SliceCap((*byte)(nil), uint64(n))
+               safe := saferio.SliceCap[byte](uint64(n))
                if safe < 0 {
                        errorf("%s slice too big: %d elements", value.Type(), n)
                }
@@ -656,7 +656,7 @@ func (dec *Decoder) decodeSlice(state *decoderState, value reflect.Value, elemOp
                errorf("%s slice too big: %d elements of %d bytes", typ.Elem(), u, size)
        }
        if value.Cap() < n {
-               safe := saferio.SliceCap(reflect.Zero(reflect.PointerTo(typ.Elem())).Interface(), uint64(n))
+               safe := saferio.SliceCapWithSize(size, uint64(n))
                if safe < 0 {
                        errorf("%s slice too big: %d elements of %d bytes", typ.Elem(), u, size)
                }
index 66cc044c745d93c16624218fbf0023232bed40ce..5c428e6ff49d33da783ce4129d265f3dcf57f458 100644 (file)
@@ -11,7 +11,7 @@ package saferio
 
 import (
        "io"
-       "reflect"
+       "unsafe"
 )
 
 // chunk is an arbitrary limit on how much memory we are willing
@@ -102,34 +102,31 @@ func ReadDataAt(r io.ReaderAt, n uint64, off int64) ([]byte, error) {
        return buf, nil
 }
 
-// SliceCap returns the capacity to use when allocating a slice.
+// SliceCapWithSize returns the capacity to use when allocating a slice.
 // After the slice is allocated with the capacity, it should be
 // built using append. This will avoid allocating too much memory
 // if the capacity is large and incorrect.
 //
 // A negative result means that the value is always too big.
-//
-// The element type is described by passing a pointer to a value of that type.
-// This would ideally use generics, but this code is built with
-// the bootstrap compiler which need not support generics.
-// We use a pointer so that we can handle slices of interface type.
-func SliceCap(v any, c uint64) int {
+func SliceCapWithSize(size, c uint64) int {
        if int64(c) < 0 || c != uint64(int(c)) {
                return -1
        }
-       typ := reflect.TypeOf(v)
-       if typ.Kind() != reflect.Ptr {
-               panic("SliceCap called with non-pointer type")
-       }
-       size := uint64(typ.Elem().Size())
        if size > 0 && c > (1<<64-1)/size {
                return -1
        }
        if c*size > chunk {
-               c = uint64(chunk / size)
+               c = chunk / size
                if c == 0 {
                        c = 1
                }
        }
        return int(c)
 }
+
+// SliceCap is like SliceCapWithSize but using generics.
+func SliceCap[E any](c uint64) int {
+       var v E
+       size := uint64(unsafe.Sizeof(v))
+       return SliceCapWithSize(size, c)
+}
index 356c9ebdd1a60880b8b89966b9a701b5a7481244..696356f0952072b39f944c00701aa6365319cf8f 100644 (file)
@@ -105,14 +105,14 @@ func TestReadDataAt(t *testing.T) {
 
 func TestSliceCap(t *testing.T) {
        t.Run("small", func(t *testing.T) {
-               c := SliceCap((*int)(nil), 10)
+               c := SliceCap[int](10)
                if c != 10 {
                        t.Errorf("got capacity %d, want %d", c, 10)
                }
        })
 
        t.Run("large", func(t *testing.T) {
-               c := SliceCap((*byte)(nil), 1<<30)
+               c := SliceCap[byte](1 << 30)
                if c < 0 {
                        t.Error("SliceCap failed unexpectedly")
                } else if c == 1<<30 {
@@ -121,14 +121,14 @@ func TestSliceCap(t *testing.T) {
        })
 
        t.Run("maxint", func(t *testing.T) {
-               c := SliceCap((*byte)(nil), 1<<63)
+               c := SliceCap[byte](1 << 63)
                if c >= 0 {
                        t.Errorf("SliceCap returned %d, expected failure", c)
                }
        })
 
        t.Run("overflow", func(t *testing.T) {
-               c := SliceCap((*int64)(nil), 1<<62)
+               c := SliceCap[int64](1 << 62)
                if c >= 0 {
                        t.Errorf("SliceCap returned %d, expected failure", c)
                }
index 9135822f22704431cebdd9866d353f86ddf7704d..12f78ccb69d1f8954778a6eedc3e56aa2737e4fa 100644 (file)
@@ -225,7 +225,7 @@ func NewFile(r io.ReaderAt) (*File, error) {
        if _, err := sr.Seek(int64(hdrsz)+int64(opthdr), io.SeekStart); err != nil {
                return nil, err
        }
-       c := saferio.SliceCap((**Section)(nil), uint64(nscns))
+       c := saferio.SliceCap[*Section](uint64(nscns))
        if c < 0 {
                return nil, fmt.Errorf("too many XCOFF sections (%d)", nscns)
        }
@@ -399,7 +399,7 @@ func NewFile(r io.ReaderAt) (*File, error) {
                if sect.Relptr == 0 {
                        continue
                }
-               c := saferio.SliceCap((*Reloc)(nil), uint64(sect.Nreloc))
+               c := saferio.SliceCap[Reloc](uint64(sect.Nreloc))
                if c < 0 {
                        return nil, fmt.Errorf("too many relocs (%d) for section %d", sect.Nreloc, sectNum)
                }