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  }