...
1
2
3
4
5
6
7 package quic
8
9 import (
10 "sync"
11 )
12
13
14
15
16
17
18
19 type pipe struct {
20 start int64
21 end int64
22 head *pipebuf
23 tail *pipebuf
24 }
25
26 type pipebuf struct {
27 off int64
28 b []byte
29 next *pipebuf
30 }
31
32 func (pb *pipebuf) end() int64 {
33 return pb.off + int64(len(pb.b))
34 }
35
36 var pipebufPool = sync.Pool{
37 New: func() any {
38 return &pipebuf{
39 b: make([]byte, 4096),
40 }
41 },
42 }
43
44 func newPipebuf() *pipebuf {
45 return pipebufPool.Get().(*pipebuf)
46 }
47
48 func (b *pipebuf) recycle() {
49 b.off = 0
50 b.next = nil
51 pipebufPool.Put(b)
52 }
53
54
55
56
57
58 func (p *pipe) writeAt(b []byte, off int64) {
59 end := off + int64(len(b))
60 if end > p.end {
61 p.end = end
62 } else if end <= p.start {
63 return
64 }
65
66 if off < p.start {
67
68 trim := p.start - off
69 b = b[trim:]
70 off = p.start
71 }
72
73 if p.head == nil {
74 p.head = newPipebuf()
75 p.head.off = p.start
76 p.tail = p.head
77 }
78 pb := p.head
79 if off >= p.tail.off {
80
81 pb = p.tail
82 }
83 for {
84 pboff := off - pb.off
85 if pboff < int64(len(pb.b)) {
86 n := copy(pb.b[pboff:], b)
87 if n == len(b) {
88 return
89 }
90 off += int64(n)
91 b = b[n:]
92 }
93 if pb.next == nil {
94 pb.next = newPipebuf()
95 pb.next.off = pb.off + int64(len(pb.b))
96 p.tail = pb.next
97 }
98 pb = pb.next
99 }
100 }
101
102
103
104 func (p *pipe) copy(off int64, b []byte) {
105 dst := b[:0]
106 p.read(off, len(b), func(c []byte) error {
107 dst = append(dst, c...)
108 return nil
109 })
110 }
111
112
113
114
115 func (p *pipe) read(off int64, n int, f func([]byte) error) error {
116 if off < p.start {
117 panic("invalid read range")
118 }
119 for pb := p.head; pb != nil && n > 0; pb = pb.next {
120 if off >= pb.end() {
121 continue
122 }
123 b := pb.b[off-pb.off:]
124 if len(b) > n {
125 b = b[:n]
126 }
127 off += int64(len(b))
128 n -= len(b)
129 if err := f(b); err != nil {
130 return err
131 }
132 }
133 if n > 0 {
134 panic("invalid read range")
135 }
136 return nil
137 }
138
139
140
141
142 func (p *pipe) peek(n int64) []byte {
143 pb := p.head
144 if pb == nil {
145 return nil
146 }
147 b := pb.b[p.start-pb.off:]
148 return b[:min(int64(len(b)), n)]
149 }
150
151
152
153
154
155
156 func (p *pipe) availableBuffer() []byte {
157 if p.tail == nil {
158 return nil
159 }
160 return p.tail.b[p.end-p.tail.off:]
161 }
162
163
164 func (p *pipe) discardBefore(off int64) {
165 for p.head != nil && p.head.end() < off {
166 head := p.head
167 p.head = p.head.next
168 head.recycle()
169 }
170 if p.head == nil {
171 p.tail = nil
172 }
173 p.start = off
174 p.end = max(p.end, off)
175 }
176
View as plain text