github.com/xraypb/xray-core@v1.6.6/common/buf/multi_buffer.go (about) 1 package buf 2 3 import ( 4 "io" 5 6 "github.com/xraypb/xray-core/common" 7 "github.com/xraypb/xray-core/common/errors" 8 "github.com/xraypb/xray-core/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 // SplitMulti splits the beginning of the MultiBuffer into first one, the index i and after into second one 207 func SplitMulti(mb MultiBuffer, i int) (MultiBuffer, MultiBuffer) { 208 mb2 := make(MultiBuffer, 0, len(mb)) 209 if i < len(mb) && i >= 0 { 210 mb2 = append(mb2, mb[i:]...) 211 for j := i; j < len(mb); j++ { 212 mb[j] = nil 213 } 214 mb = mb[:i] 215 } 216 return mb, mb2 217 } 218 219 // WriteMultiBuffer writes all buffers from the MultiBuffer to the Writer one by one, and return error if any, with leftover MultiBuffer. 220 func WriteMultiBuffer(writer io.Writer, mb MultiBuffer) (MultiBuffer, error) { 221 for { 222 mb2, b := SplitFirst(mb) 223 mb = mb2 224 if b == nil { 225 break 226 } 227 228 _, err := writer.Write(b.Bytes()) 229 b.Release() 230 if err != nil { 231 return mb, err 232 } 233 } 234 235 return nil, nil 236 } 237 238 // Len returns the total number of bytes in the MultiBuffer. 239 func (mb MultiBuffer) Len() int32 { 240 if mb == nil { 241 return 0 242 } 243 244 size := int32(0) 245 for _, b := range mb { 246 size += b.Len() 247 } 248 return size 249 } 250 251 // IsEmpty returns true if the MultiBuffer has no content. 252 func (mb MultiBuffer) IsEmpty() bool { 253 for _, b := range mb { 254 if !b.IsEmpty() { 255 return false 256 } 257 } 258 return true 259 } 260 261 // String returns the content of the MultiBuffer in string. 262 func (mb MultiBuffer) String() string { 263 v := make([]interface{}, len(mb)) 264 for i, b := range mb { 265 v[i] = b 266 } 267 return serial.Concat(v...) 268 } 269 270 // MultiBufferContainer is a ReadWriteCloser wrapper over MultiBuffer. 271 type MultiBufferContainer struct { 272 MultiBuffer 273 } 274 275 // Read implements io.Reader. 276 func (c *MultiBufferContainer) Read(b []byte) (int, error) { 277 if c.MultiBuffer.IsEmpty() { 278 return 0, io.EOF 279 } 280 281 mb, nBytes := SplitBytes(c.MultiBuffer, b) 282 c.MultiBuffer = mb 283 return nBytes, nil 284 } 285 286 // ReadMultiBuffer implements Reader. 287 func (c *MultiBufferContainer) ReadMultiBuffer() (MultiBuffer, error) { 288 mb := c.MultiBuffer 289 c.MultiBuffer = nil 290 return mb, nil 291 } 292 293 // Write implements io.Writer. 294 func (c *MultiBufferContainer) Write(b []byte) (int, error) { 295 c.MultiBuffer = MergeBytes(c.MultiBuffer, b) 296 return len(b), nil 297 } 298 299 // WriteMultiBuffer implements Writer. 300 func (c *MultiBufferContainer) WriteMultiBuffer(b MultiBuffer) error { 301 mb, _ := MergeMulti(c.MultiBuffer, b) 302 c.MultiBuffer = mb 303 return nil 304 } 305 306 // Close implements io.Closer. 307 func (c *MultiBufferContainer) Close() error { 308 c.MultiBuffer = ReleaseMulti(c.MultiBuffer) 309 return nil 310 }