github.com/xraypb/xray-core@v1.6.6/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 // Resize cuts the buffer at the given position. 164 func (b *Buffer) Resize(from, to int32) { 165 if from < 0 { 166 from += b.Len() 167 } 168 if to < 0 { 169 to += b.Len() 170 } 171 if to < from { 172 panic("Invalid slice") 173 } 174 b.end = b.start + to 175 b.start += from 176 } 177 178 // Advance cuts the buffer at the given position. 179 func (b *Buffer) Advance(from int32) { 180 if from < 0 { 181 from += b.Len() 182 } 183 b.start += from 184 } 185 186 // Len returns the length of the buffer content. 187 func (b *Buffer) Len() int32 { 188 if b == nil { 189 return 0 190 } 191 return b.end - b.start 192 } 193 194 // IsEmpty returns true if the buffer is empty. 195 func (b *Buffer) IsEmpty() bool { 196 return b.Len() == 0 197 } 198 199 // IsFull returns true if the buffer has no more room to grow. 200 func (b *Buffer) IsFull() bool { 201 return b != nil && b.end == int32(len(b.v)) 202 } 203 204 // Write implements Write method in io.Writer. 205 func (b *Buffer) Write(data []byte) (int, error) { 206 nBytes := copy(b.v[b.end:], data) 207 b.end += int32(nBytes) 208 return nBytes, nil 209 } 210 211 // WriteByte writes a single byte into the buffer. 212 func (b *Buffer) WriteByte(v byte) error { 213 if b.IsFull() { 214 return newError("buffer full") 215 } 216 b.v[b.end] = v 217 b.end++ 218 return nil 219 } 220 221 // WriteString implements io.StringWriter. 222 func (b *Buffer) WriteString(s string) (int, error) { 223 return b.Write([]byte(s)) 224 } 225 226 // ReadByte implements io.ByteReader 227 func (b *Buffer) ReadByte() (byte, error) { 228 if b.start == b.end { 229 return 0, io.EOF 230 } 231 232 nb := b.v[b.start] 233 b.start++ 234 return nb, nil 235 } 236 237 // ReadBytes implements bufio.Reader.ReadBytes 238 func (b *Buffer) ReadBytes(length int32) ([]byte, error) { 239 if b.end-b.start < length { 240 return nil, io.EOF 241 } 242 243 nb := b.v[b.start : b.start+length] 244 b.start += length 245 return nb, nil 246 } 247 248 // Read implements io.Reader.Read(). 249 func (b *Buffer) Read(data []byte) (int, error) { 250 if b.Len() == 0 { 251 return 0, io.EOF 252 } 253 nBytes := copy(data, b.v[b.start:b.end]) 254 if int32(nBytes) == b.Len() { 255 b.Clear() 256 } else { 257 b.start += int32(nBytes) 258 } 259 return nBytes, nil 260 } 261 262 // ReadFrom implements io.ReaderFrom. 263 func (b *Buffer) ReadFrom(reader io.Reader) (int64, error) { 264 n, err := reader.Read(b.v[b.end:]) 265 b.end += int32(n) 266 return int64(n), err 267 } 268 269 // ReadFullFrom reads exact size of bytes from given reader, or until error occurs. 270 func (b *Buffer) ReadFullFrom(reader io.Reader, size int32) (int64, error) { 271 end := b.end + size 272 if end > int32(len(b.v)) { 273 v := end 274 return 0, newError("out of bound: ", v) 275 } 276 n, err := io.ReadFull(reader, b.v[b.end:end]) 277 b.end += int32(n) 278 return int64(n), err 279 } 280 281 // String returns the string form of this Buffer. 282 func (b *Buffer) String() string { 283 return string(b.Bytes()) 284 }