-
Notifications
You must be signed in to change notification settings - Fork 1
/
file.go
89 lines (76 loc) · 1.62 KB
/
file.go
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
package gobergamot
import (
"bytes"
"errors"
"fmt"
"io"
"math"
)
type alignedMemoryFile struct {
Reader io.Reader
Alignment uint
}
type readerWithLen interface {
io.Reader
Len() int
}
var _ readerWithLen = (*bytes.Buffer)(nil)
func (f *alignedMemoryFile) size() (uint32, error) {
var size uint64
if f.Reader == nil {
return 0, errors.New("reader is nil")
}
switch reader := f.Reader.(type) {
case readerWithLen:
size = uint64(reader.Len())
case io.Seeker:
streamLen, err := reader.Seek(0, io.SeekEnd)
if err != nil {
return 0, err
}
if _, err := reader.Seek(0, io.SeekStart); err != nil {
return 0, err
}
size = uint64(streamLen)
default:
// We have failed to avoid copying the data into memory to get the size...
// git commit sudoku
buf := new(bytes.Buffer)
bufLen, err := io.Copy(buf, reader)
if err != nil {
return 0, err
}
// reader's been read, point it at buf now.
f.Reader = buf
size = uint64(bufLen)
}
if size > math.MaxUint32 {
return 0, fmt.Errorf("file with size %d too large", size)
}
return uint32(size), nil
}
type readerWithBytes interface {
io.Reader
Bytes() []byte
}
var _ readerWithBytes = (*bytes.Buffer)(nil)
func (f *alignedMemoryFile) readAll() ([]byte, error) {
if f.Reader == nil {
return nil, errors.New("reader is nil")
}
var data []byte
switch reader := f.Reader.(type) {
case readerWithBytes:
data = reader.Bytes()
default:
buf := new(bytes.Buffer)
_, err := io.Copy(buf, reader)
if err != nil {
return nil, err
}
// reader's been read, point it at buf now.
f.Reader = buf
data = buf.Bytes()
}
return data, nil
}