github.com/v2fly/v2ray-core/v5@v5.16.2-0.20240507031116-8191faa6e095/common/buf/multi_buffer.go (about) 1 package buf 2 3 import ( 4 "io" 5 6 "github.com/v2fly/v2ray-core/v5/common" 7 "github.com/v2fly/v2ray-core/v5/common/errors" 8 "github.com/v2fly/v2ray-core/v5/common/serial" 9 ) 10 11 // ReadAllToBytes reads all content from the reader into a byte array, until EOF. 12 func ReadAllToBytes(reader io.Reader) ([]byte, error) { 13 mb, err := ReadFrom(reader) 14 if err != nil { 15 return nil, err 16 } 17 if mb.Len() == 0 { 18 return nil, nil 19 } 20 b := make([]byte, mb.Len()) 21 mb, _ = SplitBytes(mb, b) 22 ReleaseMulti(mb) 23 return b, nil 24 } 25 26 // MultiBuffer is a list of Buffers. The order of Buffer matters. 27 type MultiBuffer []*Buffer 28 29 // MergeMulti merges content from src to dest, and returns the new address of dest and src 30 func MergeMulti(dest MultiBuffer, src MultiBuffer) (MultiBuffer, MultiBuffer) { 31 dest = append(dest, src...) 32 for idx := range src { 33 src[idx] = nil 34 } 35 return dest, src[:0] 36 } 37 38 // MergeBytes merges the given bytes into MultiBuffer and return the new address of the merged MultiBuffer. 39 func MergeBytes(dest MultiBuffer, src []byte) MultiBuffer { 40 n := len(dest) 41 if n > 0 && !(dest)[n-1].IsFull() { 42 nBytes, _ := (dest)[n-1].Write(src) 43 src = src[nBytes:] 44 } 45 46 for len(src) > 0 { 47 b := New() 48 nBytes, _ := b.Write(src) 49 src = src[nBytes:] 50 dest = append(dest, b) 51 } 52 53 return dest 54 } 55 56 // ReleaseMulti releases all content of the MultiBuffer, and returns an empty MultiBuffer. 57 func ReleaseMulti(mb MultiBuffer) MultiBuffer { 58 for i := range mb { 59 mb[i].Release() 60 mb[i] = nil 61 } 62 return mb[:0] 63 } 64 65 // Copy copied the beginning part of the MultiBuffer into the given byte array. 66 func (mb MultiBuffer) Copy(b []byte) int { 67 total := 0 68 for _, bb := range mb { 69 nBytes := copy(b[total:], bb.Bytes()) 70 total += nBytes 71 if int32(nBytes) < bb.Len() { 72 break 73 } 74 } 75 return total 76 } 77 78 // ReadFrom reads all content from reader until EOF. 79 func ReadFrom(reader io.Reader) (MultiBuffer, error) { 80 mb := make(MultiBuffer, 0, 16) 81 for { 82 b := New() 83 _, err := b.ReadFullFrom(reader, Size) 84 if b.IsEmpty() { 85 b.Release() 86 } else { 87 mb = append(mb, b) 88 } 89 if err != nil { 90 if errors.Cause(err) == io.EOF || errors.Cause(err) == io.ErrUnexpectedEOF { 91 return mb, nil 92 } 93 return mb, err 94 } 95 } 96 } 97 98 // SplitBytes splits the given amount of bytes from the beginning of the MultiBuffer. 99 // It returns the new address of MultiBuffer leftover, and number of bytes written into the input byte slice. 100 func SplitBytes(mb MultiBuffer, b []byte) (MultiBuffer, int) { 101 totalBytes := 0 102 endIndex := -1 103 for i := range mb { 104 pBuffer := mb[i] 105 nBytes, _ := pBuffer.Read(b) 106 totalBytes += nBytes 107 b = b[nBytes:] 108 if !pBuffer.IsEmpty() { 109 endIndex = i 110 break 111 } 112 pBuffer.Release() 113 mb[i] = nil 114 } 115 116 if endIndex == -1 { 117 mb = mb[:0] 118 } else { 119 mb = mb[endIndex:] 120 } 121 122 return mb, totalBytes 123 } 124 125 // SplitFirstBytes splits the first buffer from MultiBuffer, and then copy its content into the given slice. 126 func SplitFirstBytes(mb MultiBuffer, p []byte) (MultiBuffer, int) { 127 mb, b := SplitFirst(mb) 128 if b == nil { 129 return mb, 0 130 } 131 n := copy(p, b.Bytes()) 132 b.Release() 133 return mb, n 134 } 135 136 // Compact returns another MultiBuffer by merging all content of the given one together. 137 func Compact(mb MultiBuffer) MultiBuffer { 138 if len(mb) == 0 { 139 return mb 140 } 141 142 mb2 := make(MultiBuffer, 0, len(mb)) 143 last := mb[0] 144 145 for i := 1; i < len(mb); i++ { 146 curr := mb[i] 147 if last.Len()+curr.Len() > Size { 148 mb2 = append(mb2, last) 149 last = curr 150 } else { 151 common.Must2(last.ReadFrom(curr)) 152 curr.Release() 153 } 154 } 155 156 mb2 = append(mb2, last) 157 return mb2 158 } 159 160 // SplitFirst splits the first Buffer from the beginning of the MultiBuffer. 161 func SplitFirst(mb MultiBuffer) (MultiBuffer, *Buffer) { 162 if len(mb) == 0 { 163 return mb, nil 164 } 165 166 b := mb[0] 167 mb[0] = nil 168 mb = mb[1:] 169 return mb, b 170 } 171 172 // SplitSize splits the beginning of the MultiBuffer into another one, for at most size bytes. 173 func SplitSize(mb MultiBuffer, size int32) (MultiBuffer, MultiBuffer) { 174 if len(mb) == 0 { 175 return mb, nil 176 } 177 178 if mb[0].Len() > size { 179 b := New() 180 copy(b.Extend(size), mb[0].BytesTo(size)) 181 mb[0].Advance(size) 182 return mb, MultiBuffer{b} 183 } 184 185 totalBytes := int32(0) 186 var r MultiBuffer 187 endIndex := -1 188 for i := range mb { 189 if totalBytes+mb[i].Len() > size { 190 endIndex = i 191 break 192 } 193 totalBytes += mb[i].Len() 194 r = append(r, mb[i]) 195 mb[i] = nil 196 } 197 if endIndex == -1 { 198 // To reuse mb array 199 mb = mb[:0] 200 } else { 201 mb = mb[endIndex:] 202 } 203 return mb, r 204 } 205 206 // WriteMultiBuffer writes all buffers from the MultiBuffer to the Writer one by one, and return error if any, with leftover MultiBuffer. 207 func WriteMultiBuffer(writer io.Writer, mb MultiBuffer) (MultiBuffer, error) { 208 for { 209 mb2, b := SplitFirst(mb) 210 mb = mb2 211 if b == nil { 212 break 213 } 214 215 _, err := writer.Write(b.Bytes()) 216 b.Release() 217 if err != nil { 218 return mb, err 219 } 220 } 221 222 return nil, nil 223 } 224 225 // Len returns the total number of bytes in the MultiBuffer. 226 func (mb MultiBuffer) Len() int32 { 227 if mb == nil { 228 return 0 229 } 230 231 size := int32(0) 232 for _, b := range mb { 233 size += b.Len() 234 } 235 return size 236 } 237 238 // IsEmpty returns true if the MultiBuffer has no content. 239 func (mb MultiBuffer) IsEmpty() bool { 240 for _, b := range mb { 241 if !b.IsEmpty() { 242 return false 243 } 244 } 245 return true 246 } 247 248 // String returns the content of the MultiBuffer in string. 249 func (mb MultiBuffer) String() string { 250 v := make([]interface{}, len(mb)) 251 for i, b := range mb { 252 v[i] = b 253 } 254 return serial.Concat(v...) 255 } 256 257 // MultiBufferContainer is a ReadWriteCloser wrapper over MultiBuffer. 258 type MultiBufferContainer struct { 259 MultiBuffer 260 } 261 262 // Read implements io.Reader. 263 func (c *MultiBufferContainer) Read(b []byte) (int, error) { 264 if c.MultiBuffer.IsEmpty() { 265 return 0, io.EOF 266 } 267 268 mb, nBytes := SplitBytes(c.MultiBuffer, b) 269 c.MultiBuffer = mb 270 return nBytes, nil 271 } 272 273 // ReadMultiBuffer implements Reader. 274 func (c *MultiBufferContainer) ReadMultiBuffer() (MultiBuffer, error) { 275 mb := c.MultiBuffer 276 c.MultiBuffer = nil 277 return mb, nil 278 } 279 280 // Write implements io.Writer. 281 func (c *MultiBufferContainer) Write(b []byte) (int, error) { 282 c.MultiBuffer = MergeBytes(c.MultiBuffer, b) 283 return len(b), nil 284 } 285 286 // WriteMultiBuffer implements Writer. 287 func (c *MultiBufferContainer) WriteMultiBuffer(b MultiBuffer) error { 288 mb, _ := MergeMulti(c.MultiBuffer, b) 289 c.MultiBuffer = mb 290 return nil 291 } 292 293 // Close implements io.Closer. 294 func (c *MultiBufferContainer) Close() error { 295 c.MultiBuffer = ReleaseMulti(c.MultiBuffer) 296 return nil 297 }