...
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15 package ioutil
16
17 import (
18 "fmt"
19 "io"
20 )
21
22
23
24 type ReaderAndCloser struct {
25 io.Reader
26 io.Closer
27 }
28
29 var (
30 ErrShortRead = fmt.Errorf("ioutil: short read")
31 ErrExpectEOF = fmt.Errorf("ioutil: expect EOF")
32 )
33
34
35
36 func NewExactReadCloser(rc io.ReadCloser, totalBytes int64) io.ReadCloser {
37 return &exactReadCloser{rc: rc, totalBytes: totalBytes}
38 }
39
40 type exactReadCloser struct {
41 rc io.ReadCloser
42 br int64
43 totalBytes int64
44 }
45
46 func (e *exactReadCloser) Read(p []byte) (int, error) {
47 n, err := e.rc.Read(p)
48 e.br += int64(n)
49 if e.br > e.totalBytes {
50 return 0, ErrExpectEOF
51 }
52 if e.br < e.totalBytes && n == 0 {
53 return 0, ErrShortRead
54 }
55 return n, err
56 }
57
58 func (e *exactReadCloser) Close() error {
59 if err := e.rc.Close(); err != nil {
60 return err
61 }
62 if e.br < e.totalBytes {
63 return ErrShortRead
64 }
65 return nil
66 }
67
View as plain text