github.com/xraypb/Xray-core@v1.8.1/common/buf/buffer.go (about) 1 package buf 2 3 import ( 4 "io" 5 6 "github.com/xraypb/Xray-core/common/bytespool" 7 "github.com/xraypb/Xray-core/common/net" 8 ) 9 10 const ( 11 // Size of a regular buffer. 12 Size = 8192 13 ) 14 15 var pool = bytespool.GetPool(Size) 16 17 // Buffer is a recyclable allocation of a byte array. Buffer.Release() recycles 18 // the buffer into an internal buffer pool, in order to recreate a buffer more 19 // quickly. 20 type Buffer struct { 21 v []byte 22 start int32 23 end int32 24 unmanaged bool 25 UDP *net.Destination 26 } 27 28 // New creates a Buffer with 0 length and 8K capacity. 29 func New() *Buffer { 30 buf := pool.Get().([]byte) 31 if cap(buf) >= Size { 32 buf = buf[:Size] 33 } else { 34 buf = make([]byte, Size) 35 } 36 37 return &Buffer{ 38 v: buf, 39 } 40 } 41 42 // NewExisted creates a managed, standard size Buffer with an existed bytearray 43 func NewExisted(b []byte) *Buffer { 44 if cap(b) < Size { 45 panic("Invalid buffer") 46 } 47 48 oLen := len(b) 49 if oLen < Size { 50 b = b[:Size] 51 } 52 53 return &Buffer{ 54 v: b, 55 end: int32(oLen), 56 } 57 } 58 59 // FromBytes creates a Buffer with an existed bytearray 60 func FromBytes(b []byte) *Buffer { 61 return &Buffer{ 62 v: b, 63 end: int32(len(b)), 64 unmanaged: true, 65 } 66 } 67 68 // StackNew creates a new Buffer object on stack. 69 // This method is for buffers that is released in the same function. 70 func StackNew() Buffer { 71 buf := pool.Get().([]byte) 72 if cap(buf) >= Size { 73 buf = buf[:Size] 74 } else { 75 buf = make([]byte, Size) 76 } 77 78 return Buffer{ 79 v: buf, 80 } 81 } 82 83 // Release recycles the buffer into an internal buffer pool. 84 func (b *Buffer) Release() { 85 if b == nil || b.v == nil || b.unmanaged { 86 return 87 } 88 89 p := b.v 90 b.v = nil 91 b.Clear() 92 93 if cap(p) == Size { 94 pool.Put(p) 95 } 96 b.UDP = nil 97 } 98 99 // Clear clears the content of the buffer, results an empty buffer with 100 // Len() = 0. 101 func (b *Buffer) Clear() { 102 b.start = 0 103 b.end = 0 104 } 105 106 // Byte returns the bytes at index. 107 func (b *Buffer) Byte(index int32) byte { 108 return b.v[b.start+index] 109 } 110 111 // SetByte sets the byte value at index. 112 func (b *Buffer) SetByte(index int32, value byte) { 113 b.v[b.start+index] = value 114 } 115 116 // Bytes returns the content bytes of this Buffer. 117 func (b *Buffer) Bytes() []byte { 118 return b.v[b.start:b.end] 119 } 120 121 // Extend increases the buffer size by n bytes, and returns the extended part. 122 // It panics if result size is larger than buf.Size. 123 func (b *Buffer) Extend(n int32) []byte { 124 end := b.end + n 125 if end > int32(len(b.v)) { 126 panic("extending out of bound") 127 } 128 ext := b.v[b.end:end] 129 b.end = end 130 return ext 131 } 132 133 // BytesRange returns a slice of this buffer with given from and to boundary. 134 func (b *Buffer) BytesRange(from, to int32) []byte { 135 if from < 0 { 136 from += b.Len() 137 } 138 if to < 0 { 139 to += b.Len() 140 } 141 return b.v[b.start+from : b.start+to] 142 } 143 144 // BytesFrom returns a slice of this Buffer starting from the given position. 145 func (b *Buffer) BytesFrom(from int32) []byte { 146 if from < 0 { 147 from += b.Len() 148 } 149 return b.v[b.start+from : b.end] 150 } 151 152 // BytesTo returns a slice of this Buffer from start to the given position. 153 func (b *Buffer) BytesTo(to int32) []byte { 154 if to < 0 { 155 to += b.Len() 156 } 157 if to < 0 { 158 to = 0 159 } 160 return b.v[b.start : b.start+to] 161 } 162 163 // Check makes sure that 0 <= b.start <= b.end. 164 func (b *Buffer) Check() { 165 if b.start < 0 { 166 b.start = 0 167 } 168 if b.end < 0 { 169 b.end = 0 170 } 171 if b.start > b.end { 172 b.start = b.end 173 } 174 } 175 176 // Resize cuts the buffer at the given position. 177 func (b *Buffer) Resize(from, to int32) { 178 if from < 0 { 179 from += b.Len() 180 } 181 if to < 0 { 182 to += b.Len() 183 } 184 if to < from { 185 panic("Invalid slice") 186 } 187 b.end = b.start + to 188 b.start += from 189 b.Check() 190 } 191 192 // Advance cuts the buffer at the given position. 193 func (b *Buffer) Advance(from int32) { 194 if from < 0 { 195 from += b.Len() 196 } 197 b.start += from 198 b.Check() 199 } 200 201 // Len returns the length of the buffer content. 202 func (b *Buffer) Len() int32 { 203 if b == nil { 204 return 0 205 } 206 return b.end - b.start 207 } 208 209 // IsEmpty returns true if the buffer is empty. 210 func (b *Buffer) IsEmpty() bool { 211 return b.Len() == 0 212 } 213 214 // IsFull returns true if the buffer has no more room to grow. 215 func (b *Buffer) IsFull() bool { 216 return b != nil && b.end == int32(len(b.v)) 217 } 218 219 // Write implements Write method in io.Writer. 220 func (b *Buffer) Write(data []byte) (int, error) { 221 nBytes := copy(b.v[b.end:], data) 222 b.end += int32(nBytes) 223 return nBytes, nil 224 } 225 226 // WriteByte writes a single byte into the buffer. 227 func (b *Buffer) WriteByte(v byte) error { 228 if b.IsFull() { 229 return newError("buffer full") 230 } 231 b.v[b.end] = v 232 b.end++ 233 return nil 234 } 235 236 // WriteString implements io.StringWriter. 237 func (b *Buffer) WriteString(s string) (int, error) { 238 return b.Write([]byte(s)) 239 } 240 241 // ReadByte implements io.ByteReader 242 func (b *Buffer) ReadByte() (byte, error) { 243 if b.start == b.end { 244 return 0, io.EOF 245 } 246 247 nb := b.v[b.start] 248 b.start++ 249 return nb, nil 250 } 251 252 // ReadBytes implements bufio.Reader.ReadBytes 253 func (b *Buffer) ReadBytes(length int32) ([]byte, error) { 254 if b.end-b.start < length { 255 return nil, io.EOF 256 } 257 258 nb := b.v[b.start : b.start+length] 259 b.start += length 260 return nb, nil 261 } 262 263 // Read implements io.Reader.Read(). 264 func (b *Buffer) Read(data []byte) (int, error) { 265 if b.Len() == 0 { 266 return 0, io.EOF 267 } 268 nBytes := copy(data, b.v[b.start:b.end]) 269 if int32(nBytes) == b.Len() { 270 b.Clear() 271 } else { 272 b.start += int32(nBytes) 273 } 274 return nBytes, nil 275 } 276 277 // ReadFrom implements io.ReaderFrom. 278 func (b *Buffer) ReadFrom(reader io.Reader) (int64, error) { 279 n, err := reader.Read(b.v[b.end:]) 280 b.end += int32(n) 281 return int64(n), err 282 } 283 284 // ReadFullFrom reads exact size of bytes from given reader, or until error occurs. 285 func (b *Buffer) ReadFullFrom(reader io.Reader, size int32) (int64, error) { 286 end := b.end + size 287 if end > int32(len(b.v)) { 288 v := end 289 return 0, newError("out of bound: ", v) 290 } 291 n, err := io.ReadFull(reader, b.v[b.end:end]) 292 b.end += int32(n) 293 return int64(n), err 294 } 295 296 // String returns the string form of this Buffer. 297 func (b *Buffer) String() string { 298 return string(b.Bytes()) 299 }