forked from djherbis/buffer
-
Notifications
You must be signed in to change notification settings - Fork 0
/
swap.go
99 lines (81 loc) · 2.05 KB
/
swap.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
90
91
92
93
94
95
96
97
98
99
package buffer
import (
"encoding/gob"
"io"
)
type swap struct {
A BufferAt
B BufferAt
}
// NewSwap creates a Buffer which writes to a until you write past a.Cap()
// then it io.Copy's from a to b and writes to b.
// Once the Buffer is empty again, it starts over writing to a.
// Note that if b.Cap() <= a.Cap() it will cause a panic, b is expected
// to be larger in order to accommodate writes past a.Cap().
func NewSwap(a, b Buffer) Buffer {
return NewSwapAt(toBufferAt(a), toBufferAt(b))
}
// NewSwapAt creates a BufferAt which writes to a until you write past a.Cap()
// then it io.Copy's from a to b and writes to b.
// Once the Buffer is empty again, it starts over writing to a.
// Note that if b.Cap() <= a.Cap() it will cause a panic, b is expected
// to be larger in order to accommodate writes past a.Cap().
func NewSwapAt(a, b BufferAt) BufferAt {
if b.Cap() <= a.Cap() {
panic("Buffer b must be larger than a.")
}
return &swap{A: a, B: b}
}
func (buf *swap) Len() int64 {
return buf.A.Len() + buf.B.Len()
}
func (buf *swap) Cap() int64 {
return buf.B.Cap()
}
func (buf *swap) Read(p []byte) (n int, err error) {
if buf.A.Len() > 0 {
return buf.A.Read(p)
}
return buf.B.Read(p)
}
func (buf *swap) ReadAt(p []byte, off int64) (n int, err error) {
if buf.A.Len() > 0 {
return buf.A.ReadAt(p, off)
}
return buf.B.ReadAt(p, off)
}
func (buf *swap) Write(p []byte) (n int, err error) {
switch {
case buf.B.Len() > 0:
n, err = buf.B.Write(p)
case buf.A.Len()+int64(len(p)) > buf.A.Cap():
_, err = io.Copy(buf.B, buf.A)
if err == nil {
n, err = buf.B.Write(p)
}
default:
n, err = buf.A.Write(p)
}
return n, err
}
func (buf *swap) WriteAt(p []byte, off int64) (n int, err error) {
switch {
case buf.B.Len() > 0:
n, err = buf.B.WriteAt(p, off)
case off+int64(len(p)) > buf.A.Cap():
_, err = io.Copy(buf.B, buf.A)
if err == nil {
n, err = buf.B.WriteAt(p, off)
}
default:
n, err = buf.A.WriteAt(p, off)
}
return n, err
}
func (buf *swap) Reset() {
buf.A.Reset()
buf.B.Reset()
}
func init() {
gob.Register(&swap{})
}