1
2
3
4
5
6
7
8
9
10 package saferio
11
12 import (
13 "io"
14 "unsafe"
15 )
16
17
18
19 const chunk = 10 << 20
20
21
22
23
24
25
26
27
28 func ReadData(r io.Reader, n uint64) ([]byte, error) {
29 if int64(n) < 0 || n != uint64(int(n)) {
30
31
32 return nil, io.ErrUnexpectedEOF
33 }
34
35 if n < chunk {
36 buf := make([]byte, n)
37 _, err := io.ReadFull(r, buf)
38 if err != nil {
39 return nil, err
40 }
41 return buf, nil
42 }
43
44 var buf []byte
45 buf1 := make([]byte, chunk)
46 for n > 0 {
47 next := n
48 if next > chunk {
49 next = chunk
50 }
51 _, err := io.ReadFull(r, buf1[:next])
52 if err != nil {
53 if len(buf) > 0 && err == io.EOF {
54 err = io.ErrUnexpectedEOF
55 }
56 return nil, err
57 }
58 buf = append(buf, buf1[:next]...)
59 n -= next
60 }
61 return buf, nil
62 }
63
64
65
66
67 func ReadDataAt(r io.ReaderAt, n uint64, off int64) ([]byte, error) {
68 if int64(n) < 0 || n != uint64(int(n)) {
69
70
71 return nil, io.ErrUnexpectedEOF
72 }
73
74 if n < chunk {
75 buf := make([]byte, n)
76 _, err := r.ReadAt(buf, off)
77 if err != nil {
78
79
80 if err != io.EOF || n > 0 {
81 return nil, err
82 }
83 }
84 return buf, nil
85 }
86
87 var buf []byte
88 buf1 := make([]byte, chunk)
89 for n > 0 {
90 next := n
91 if next > chunk {
92 next = chunk
93 }
94 _, err := r.ReadAt(buf1[:next], off)
95 if err != nil {
96 return nil, err
97 }
98 buf = append(buf, buf1[:next]...)
99 n -= next
100 off += int64(next)
101 }
102 return buf, nil
103 }
104
105
106
107
108
109
110
111 func SliceCapWithSize(size, c uint64) int {
112 if int64(c) < 0 || c != uint64(int(c)) {
113 return -1
114 }
115 if size > 0 && c > (1<<64-1)/size {
116 return -1
117 }
118 if c*size > chunk {
119 c = chunk / size
120 if c == 0 {
121 c = 1
122 }
123 }
124 return int(c)
125 }
126
127
128 func SliceCap[E any](c uint64) int {
129 var v E
130 size := uint64(unsafe.Sizeof(v))
131 return SliceCapWithSize(size, c)
132 }
133
View as plain text