aboutsummaryrefslogtreecommitdiff
path: root/format/pktline/chunk_writer.go
blob: b258ff20a37424d134e4bec796c9620cb7b2eb1b (about) (plain) (blame)
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
package pktline

import "io"

// ChunkWriter packetizes arbitrary stream bytes into data pkt-lines.
// It never writes control packets automatically.
type ChunkWriter struct {
	enc *Encoder
}

// NewChunkWriter creates a chunking adapter over enc.
func NewChunkWriter(enc *Encoder) *ChunkWriter {
	return &ChunkWriter{enc: enc}
}

// Write splits p into data frames not larger than enc's maxData.
//
// It implements io.Writer.
func (cw *ChunkWriter) Write(p []byte) (int, error) {
	total := 0
	maxData := cw.enc.effectiveMaxData()

	for len(p) > 0 {
		n := min(len(p), maxData)

		err := cw.enc.WriteData(p[:n])
		if err != nil {
			return total, err
		}

		total += n
		p = p[n:]
	}

	return total, nil
}

// ReadFrom reads from r and writes pkt-line data frames to the encoder.
//
// It implements io.ReaderFrom.
func (cw *ChunkWriter) ReadFrom(r io.Reader) (int64, error) {
	buf := make([]byte, cw.enc.effectiveMaxData())

	var total int64

	for {
		n, err := r.Read(buf)
		if n > 0 {
			werr := cw.enc.WriteData(buf[:n])
			if werr != nil {
				return total, werr
			}

			total += int64(n)
		}

		if err != nil {
			if err == io.EOF {
				return total, nil
			}

			return total, err
		}
	}
}