github.com/flowerwrong/netstack@v0.0.0-20191009141956-e5848263af28/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 // View is a slice of a buffer, with convenience methods. 19 type View []byte 20 21 // NewView allocates a new buffer and returns an initialized view that covers 22 // the whole buffer. 23 func NewView(size int) View { 24 return make(View, size) 25 } 26 27 // NewViewFromBytes allocates a new buffer and copies in the given bytes. 28 func NewViewFromBytes(b []byte) View { 29 return append(View(nil), b...) 30 } 31 32 // TrimFront removes the first "count" bytes from the visible section of the 33 // buffer. 34 func (v *View) TrimFront(count int) { 35 *v = (*v)[count:] 36 } 37 38 // CapLength irreversibly reduces the length of the visible section of the 39 // buffer to the value specified. 40 func (v *View) CapLength(length int) { 41 // We also set the slice cap because if we don't, one would be able to 42 // expand the view back to include the region just excluded. We want to 43 // prevent that to avoid potential data leak if we have uninitialized 44 // data in excluded region. 45 *v = (*v)[:length:length] 46 } 47 48 // ToVectorisedView returns a VectorisedView containing the receiver. 49 func (v View) ToVectorisedView() VectorisedView { 50 return NewVectorisedView(len(v), []View{v}) 51 } 52 53 // VectorisedView is a vectorised version of View using non contiguous memory. 54 // It supports all the convenience methods supported by View. 55 // 56 // +stateify savable 57 type VectorisedView struct { 58 views []View 59 size int 60 } 61 62 // NewVectorisedView creates a new vectorised view from an already-allocated slice 63 // of View and sets its size. 64 func NewVectorisedView(size int, views []View) VectorisedView { 65 return VectorisedView{views: views, size: size} 66 } 67 68 // TrimFront removes the first "count" bytes of the vectorised view. 69 func (vv *VectorisedView) TrimFront(count int) { 70 for count > 0 && len(vv.views) > 0 { 71 if count < len(vv.views[0]) { 72 vv.size -= count 73 vv.views[0].TrimFront(count) 74 return 75 } 76 count -= len(vv.views[0]) 77 vv.RemoveFirst() 78 } 79 } 80 81 // CapLength irreversibly reduces the length of the vectorised view. 82 func (vv *VectorisedView) CapLength(length int) { 83 if length < 0 { 84 length = 0 85 } 86 if vv.size < length { 87 return 88 } 89 vv.size = length 90 for i := range vv.views { 91 v := &vv.views[i] 92 if len(*v) >= length { 93 if length == 0 { 94 vv.views = vv.views[:i] 95 } else { 96 v.CapLength(length) 97 vv.views = vv.views[:i+1] 98 } 99 return 100 } 101 length -= len(*v) 102 } 103 } 104 105 // Clone returns a clone of this VectorisedView. 106 // If the buffer argument is large enough to contain all the Views of this VectorisedView, 107 // the method will avoid allocations and use the buffer to store the Views of the clone. 108 func (vv VectorisedView) Clone(buffer []View) VectorisedView { 109 return VectorisedView{views: append(buffer[:0], vv.views...), size: vv.size} 110 } 111 112 // First returns the first view of the vectorised view. 113 func (vv VectorisedView) First() View { 114 if len(vv.views) == 0 { 115 return nil 116 } 117 return vv.views[0] 118 } 119 120 // RemoveFirst removes the first view of the vectorised view. 121 func (vv *VectorisedView) RemoveFirst() { 122 if len(vv.views) == 0 { 123 return 124 } 125 vv.size -= len(vv.views[0]) 126 vv.views = vv.views[1:] 127 } 128 129 // Size returns the size in bytes of the entire content stored in the vectorised view. 130 func (vv VectorisedView) Size() int { 131 return vv.size 132 } 133 134 // ToView returns a single view containing the content of the vectorised view. 135 // 136 // If the vectorised view contains a single view, that view will be returned 137 // directly. 138 func (vv VectorisedView) ToView() View { 139 if len(vv.views) == 1 { 140 return vv.views[0] 141 } 142 u := make([]byte, 0, vv.size) 143 for _, v := range vv.views { 144 u = append(u, v...) 145 } 146 return u 147 } 148 149 // Views returns the slice containing the all views. 150 func (vv VectorisedView) Views() []View { 151 return vv.views 152 } 153 154 // Append appends the views in a vectorised view to this vectorised view. 155 func (vv *VectorisedView) Append(vv2 VectorisedView) { 156 vv.views = append(vv.views, vv2.views...) 157 vv.size += vv2.size 158 }