github.com/SagerNet/gvisor@v0.0.0-20210707092255-7731c139d75c/pkg/tcpip/buffer/view.go (about) 1 // Copyright 2018 The gVisor Authors. 2 // 3 // Licensed under the Apache License, Version 2.0 (the "License"); 4 // you may not use this file except in compliance with the License. 5 // You may obtain a copy of the License at 6 // 7 // http://www.apache.org/licenses/LICENSE-2.0 8 // 9 // Unless required by applicable law or agreed to in writing, software 10 // distributed under the License is distributed on an "AS IS" BASIS, 11 // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 // See the License for the specific language governing permissions and 13 // limitations under the License. 14 15 // Package buffer provides the implementation of a buffer view. 16 package buffer 17 18 import ( 19 "bytes" 20 "fmt" 21 "io" 22 ) 23 24 // View is a slice of a buffer, with convenience methods. 25 type View []byte 26 27 // NewView allocates a new buffer and returns an initialized view that covers 28 // the whole buffer. 29 func NewView(size int) View { 30 return make(View, size) 31 } 32 33 // NewViewFromBytes allocates a new buffer and copies in the given bytes. 34 func NewViewFromBytes(b []byte) View { 35 return append(View(nil), b...) 36 } 37 38 // TrimFront removes the first "count" bytes from the visible section of the 39 // buffer. 40 func (v *View) TrimFront(count int) { 41 *v = (*v)[count:] 42 } 43 44 // CapLength irreversibly reduces the length of the visible section of the 45 // buffer to the value specified. 46 func (v *View) CapLength(length int) { 47 // We also set the slice cap because if we don't, one would be able to 48 // expand the view back to include the region just excluded. We want to 49 // prevent that to avoid potential data leak if we have uninitialized 50 // data in excluded region. 51 *v = (*v)[:length:length] 52 } 53 54 // Reader returns a bytes.Reader for v. 55 func (v *View) Reader() bytes.Reader { 56 var r bytes.Reader 57 r.Reset(*v) 58 return r 59 } 60 61 // ToVectorisedView returns a VectorisedView containing the receiver. 62 func (v View) ToVectorisedView() VectorisedView { 63 if len(v) == 0 { 64 return VectorisedView{} 65 } 66 return NewVectorisedView(len(v), []View{v}) 67 } 68 69 // IsEmpty returns whether v is of length zero. 70 func (v View) IsEmpty() bool { 71 return len(v) == 0 72 } 73 74 // Size returns the length of v. 75 func (v View) Size() int { 76 return len(v) 77 } 78 79 // VectorisedView is a vectorised version of View using non contiguous memory. 80 // It supports all the convenience methods supported by View. 81 // 82 // +stateify savable 83 type VectorisedView struct { 84 views []View 85 size int 86 } 87 88 // NewVectorisedView creates a new vectorised view from an already-allocated 89 // slice of View and sets its size. 90 func NewVectorisedView(size int, views []View) VectorisedView { 91 return VectorisedView{views: views, size: size} 92 } 93 94 // TrimFront removes the first "count" bytes of the vectorised view. It panics 95 // if count > vv.Size(). 96 func (vv *VectorisedView) TrimFront(count int) { 97 for count > 0 && len(vv.views) > 0 { 98 if count < len(vv.views[0]) { 99 vv.size -= count 100 vv.views[0].TrimFront(count) 101 return 102 } 103 count -= len(vv.views[0]) 104 vv.removeFirst() 105 } 106 } 107 108 // Read implements io.Reader. 109 func (vv *VectorisedView) Read(b []byte) (copied int, err error) { 110 count := len(b) 111 for count > 0 && len(vv.views) > 0 { 112 if count < len(vv.views[0]) { 113 vv.size -= count 114 copy(b[copied:], vv.views[0][:count]) 115 vv.views[0].TrimFront(count) 116 copied += count 117 return copied, nil 118 } 119 count -= len(vv.views[0]) 120 copy(b[copied:], vv.views[0]) 121 copied += len(vv.views[0]) 122 vv.removeFirst() 123 } 124 if copied == 0 { 125 return 0, io.EOF 126 } 127 return copied, nil 128 } 129 130 // ReadToVV reads up to n bytes from vv to dstVV and removes them from vv. It 131 // returns the number of bytes copied. 132 func (vv *VectorisedView) ReadToVV(dstVV *VectorisedView, count int) (copied int) { 133 for count > 0 && len(vv.views) > 0 { 134 if count < len(vv.views[0]) { 135 vv.size -= count 136 dstVV.AppendView(vv.views[0][:count]) 137 vv.views[0].TrimFront(count) 138 copied += count 139 return 140 } 141 count -= len(vv.views[0]) 142 dstVV.AppendView(vv.views[0]) 143 copied += len(vv.views[0]) 144 vv.removeFirst() 145 } 146 return copied 147 } 148 149 // ReadTo reads up to count bytes from vv to dst. It also removes them from vv 150 // unless peek is true. 151 func (vv *VectorisedView) ReadTo(dst io.Writer, peek bool) (int, error) { 152 var err error 153 done := 0 154 for _, v := range vv.Views() { 155 var n int 156 n, err = dst.Write(v) 157 done += n 158 if err != nil { 159 break 160 } 161 if n != len(v) { 162 panic(fmt.Sprintf("io.Writer.Write succeeded with incomplete write: %d != %d", n, len(v))) 163 } 164 } 165 if !peek { 166 vv.TrimFront(done) 167 } 168 return done, err 169 } 170 171 // CapLength irreversibly reduces the length of the vectorised view. 172 func (vv *VectorisedView) CapLength(length int) { 173 if length < 0 { 174 length = 0 175 } 176 if vv.size < length { 177 return 178 } 179 vv.size = length 180 for i := range vv.views { 181 v := &vv.views[i] 182 if len(*v) >= length { 183 if length == 0 { 184 vv.views = vv.views[:i] 185 } else { 186 v.CapLength(length) 187 vv.views = vv.views[:i+1] 188 } 189 return 190 } 191 length -= len(*v) 192 } 193 } 194 195 // Clone returns a clone of this VectorisedView. 196 // If the buffer argument is large enough to contain all the Views of this 197 // VectorisedView, the method will avoid allocations and use the buffer to 198 // store the Views of the clone. 199 func (vv VectorisedView) Clone(buffer []View) VectorisedView { 200 return VectorisedView{views: append(buffer[:0], vv.views...), size: vv.size} 201 } 202 203 // PullUp returns the first "count" bytes of the vectorised view. If those 204 // bytes aren't already contiguous inside the vectorised view, PullUp will 205 // reallocate as needed to make them contiguous. PullUp fails and returns false 206 // when count > vv.Size(). 207 func (vv *VectorisedView) PullUp(count int) (View, bool) { 208 if len(vv.views) == 0 { 209 return nil, count == 0 210 } 211 if count <= len(vv.views[0]) { 212 return vv.views[0][:count], true 213 } 214 if count > vv.size { 215 return nil, false 216 } 217 218 newFirst := NewView(count) 219 i := 0 220 for offset := 0; offset < count; i++ { 221 copy(newFirst[offset:], vv.views[i]) 222 if count-offset < len(vv.views[i]) { 223 vv.views[i].TrimFront(count - offset) 224 break 225 } 226 offset += len(vv.views[i]) 227 vv.views[i] = nil 228 } 229 // We're guaranteed that i > 0, since count is too large for the first 230 // view. 231 vv.views[i-1] = newFirst 232 vv.views = vv.views[i-1:] 233 return newFirst, true 234 } 235 236 // Size returns the size in bytes of the entire content stored in the 237 // vectorised view. 238 func (vv *VectorisedView) Size() int { 239 return vv.size 240 } 241 242 // MemSize returns the estimation size of the vv in memory, including backing 243 // buffer data. 244 func (vv *VectorisedView) MemSize() int { 245 var size int 246 for _, v := range vv.views { 247 size += cap(v) 248 } 249 return size + cap(vv.views)*viewStructSize + vectorisedViewStructSize 250 } 251 252 // ToView returns a single view containing the content of the vectorised view. 253 // 254 // If the vectorised view contains a single view, that view will be returned 255 // directly. 256 func (vv *VectorisedView) ToView() View { 257 if len(vv.views) == 1 { 258 return vv.views[0] 259 } 260 return vv.ToOwnedView() 261 } 262 263 // ToOwnedView returns a single view containing the content of the vectorised 264 // view that vv does not own. 265 func (vv *VectorisedView) ToOwnedView() View { 266 u := make([]byte, 0, vv.size) 267 for _, v := range vv.views { 268 u = append(u, v...) 269 } 270 return u 271 } 272 273 // Views returns the slice containing the all views. 274 func (vv *VectorisedView) Views() []View { 275 return vv.views 276 } 277 278 // Append appends the views in a vectorised view to this vectorised view. 279 func (vv *VectorisedView) Append(vv2 VectorisedView) { 280 vv.views = append(vv.views, vv2.views...) 281 vv.size += vv2.size 282 } 283 284 // AppendView appends the given view into this vectorised view. 285 func (vv *VectorisedView) AppendView(v View) { 286 if len(v) == 0 { 287 return 288 } 289 vv.views = append(vv.views, v) 290 vv.size += len(v) 291 } 292 293 // AppendViews appends views to vv. 294 func (vv *VectorisedView) AppendViews(views []View) { 295 vv.views = append(vv.views, views...) 296 for _, v := range views { 297 vv.size += len(v) 298 } 299 } 300 301 // Readers returns a bytes.Reader for each of vv's views. 302 func (vv *VectorisedView) Readers() []bytes.Reader { 303 readers := make([]bytes.Reader, 0, len(vv.views)) 304 for _, v := range vv.views { 305 readers = append(readers, v.Reader()) 306 } 307 return readers 308 } 309 310 // removeFirst panics when len(vv.views) < 1. 311 func (vv *VectorisedView) removeFirst() { 312 vv.size -= len(vv.views[0]) 313 vv.views[0] = nil 314 vv.views = vv.views[1:] 315 }