-
Notifications
You must be signed in to change notification settings - Fork 84
/
chunk.go
71 lines (67 loc) · 1.47 KB
/
chunk.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
package gofakes3
import (
"fmt"
"io"
"io/ioutil"
)
type chunkedReader struct {
inner io.Reader
chunkRemain int
notFirstChunk bool
}
func newChunkedReader(inner io.Reader) *chunkedReader {
return &chunkedReader{
inner: inner,
chunkRemain: 0,
notFirstChunk: false,
}
}
func (r *chunkedReader) Read(p []byte) (n int, err error) {
sizeToRead := len(p)
for sizeToRead > 0 {
if r.chunkRemain > sizeToRead {
r.chunkRemain -= sizeToRead
// read sizeToRead bytes from inner reader
// to p, start from n.
// n is bytes already read.
innerN, err := r.inner.Read(p[n : n+sizeToRead])
sizeToRead -= innerN
n += innerN
if err != nil {
return n, err
}
} else if r.chunkRemain > 0 {
// read until this chunk ends
innerN, err := r.inner.Read(p[n : n+r.chunkRemain])
r.chunkRemain -= innerN
n += innerN
sizeToRead -= innerN
if err != nil {
return n, err
}
} else {
if !r.notFirstChunk {
// Is first chunk.
r.notFirstChunk = true
} else {
// skip last chunk's b"\r\n"
_, err = io.CopyN(ioutil.Discard, r.inner, 2)
if err != nil {
return n, err
}
}
// read next chunk header
chunkSize := 0
_, err = fmt.Fscanf(r.inner, "%x;", &chunkSize)
if err != nil {
return n, err
}
r.chunkRemain = chunkSize
_, err = io.CopyN(ioutil.Discard, r.inner, 16+64+2) // "chunk-signature=" + sizeOfHash + "\r\n"
if err != nil {
return n, err
}
}
}
return n, nil
}