gvisor.dev/gvisor@v0.0.0-20240520182842-f9d4d51c7e0f/pkg/tcpip/prependable/prependable.go (about) 1 // Copyright 2022 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 prependable defines a buffer that grows backwards. 16 package prependable 17 18 // Prependable is a buffer that grows backwards, that is, more data can be 19 // prepended to it. It is useful when building networking packets, where each 20 // protocol adds its own headers to the front of the higher-level protocol 21 // header and payload; for example, TCP would prepend its header to the payload, 22 // then IP would prepend its own, then ethernet. 23 type Prependable struct { 24 // Buf is the buffer backing the prependable buffer. 25 buf []byte 26 27 // usedIdx is the index where the used part of the buffer begins. 28 usedIdx int 29 } 30 31 // New allocates a new prependable buffer with the given size. 32 func New(size int) Prependable { 33 return Prependable{buf: make([]byte, size), usedIdx: size} 34 } 35 36 // NewFromSlice creates an entirely-used Prependable from a slice. 37 // 38 // NewFromSlice takes ownership of v. Note that since the entire 39 // prependable is used, further attempts to call Prepend will note that size > 40 // p.usedIdx and return nil. 41 func NewFromSlice(v []byte) Prependable { 42 return Prependable{buf: v, usedIdx: 0} 43 } 44 45 // NewEmptyFromSlice creates a new prependable buffer from a slice. 46 func NewEmptyFromSlice(v []byte) Prependable { 47 return Prependable{buf: v, usedIdx: len(v)} 48 } 49 50 // View returns a slice of the backing buffer that contains all prepended 51 // data so far. 52 func (p Prependable) View() []byte { 53 return p.buf[p.usedIdx:] 54 } 55 56 // UsedLength returns the number of bytes used so far. 57 func (p Prependable) UsedLength() int { 58 return len(p.buf) - p.usedIdx 59 } 60 61 // AvailableLength returns the number of bytes used so far. 62 func (p Prependable) AvailableLength() int { 63 return p.usedIdx 64 } 65 66 // TrimBack removes size bytes from the end. 67 func (p *Prependable) TrimBack(size int) { 68 p.buf = p.buf[:len(p.buf)-size] 69 } 70 71 // Prepend reserves the requested space in front of the buffer, returning a 72 // slice that represents the reserved space. 73 func (p *Prependable) Prepend(size int) []byte { 74 if size > p.usedIdx { 75 return nil 76 } 77 78 p.usedIdx -= size 79 return p.View()[:size:size] 80 } 81 82 // DeepCopy copies p and the bytes backing it. 83 func (p Prependable) DeepCopy() Prependable { 84 p.buf = append([]byte{}, p.buf...) 85 return p 86 }