github.com/xmplusdev/xmcore@v1.8.11-0.20240412132628-5518b55526af/common/buf/writer.go (about) 1 package buf 2 3 import ( 4 "io" 5 "net" 6 "sync" 7 8 "github.com/xmplusdev/xmcore/common" 9 "github.com/xmplusdev/xmcore/common/errors" 10 "github.com/xmplusdev/xmcore/features/stats" 11 ) 12 13 // BufferToBytesWriter is a Writer that writes alloc.Buffer into underlying writer. 14 type BufferToBytesWriter struct { 15 io.Writer 16 17 counter stats.Counter 18 cache [][]byte 19 } 20 21 // WriteMultiBuffer implements Writer. This method takes ownership of the given buffer. 22 func (w *BufferToBytesWriter) WriteMultiBuffer(mb MultiBuffer) error { 23 defer ReleaseMulti(mb) 24 25 size := mb.Len() 26 if size == 0 { 27 return nil 28 } 29 30 if len(mb) == 1 { 31 return WriteAllBytes(w.Writer, mb[0].Bytes(), w.counter) 32 } 33 34 if cap(w.cache) < len(mb) { 35 w.cache = make([][]byte, 0, len(mb)) 36 } 37 38 bs := w.cache 39 for _, b := range mb { 40 bs = append(bs, b.Bytes()) 41 } 42 43 defer func() { 44 for idx := range bs { 45 bs[idx] = nil 46 } 47 }() 48 49 nb := net.Buffers(bs) 50 wc := int64(0) 51 defer func() { 52 if w.counter != nil { 53 w.counter.Add(wc) 54 } 55 }() 56 for size > 0 { 57 n, err := nb.WriteTo(w.Writer) 58 wc += n 59 if err != nil { 60 return err 61 } 62 size -= int32(n) 63 } 64 65 return nil 66 } 67 68 // ReadFrom implements io.ReaderFrom. 69 func (w *BufferToBytesWriter) ReadFrom(reader io.Reader) (int64, error) { 70 var sc SizeCounter 71 err := Copy(NewReader(reader), w, CountSize(&sc)) 72 return sc.Size, err 73 } 74 75 // BufferedWriter is a Writer with internal buffer. 76 type BufferedWriter struct { 77 sync.Mutex 78 writer Writer 79 buffer *Buffer 80 buffered bool 81 } 82 83 // NewBufferedWriter creates a new BufferedWriter. 84 func NewBufferedWriter(writer Writer) *BufferedWriter { 85 return &BufferedWriter{ 86 writer: writer, 87 buffer: New(), 88 buffered: true, 89 } 90 } 91 92 // WriteByte implements io.ByteWriter. 93 func (w *BufferedWriter) WriteByte(c byte) error { 94 return common.Error2(w.Write([]byte{c})) 95 } 96 97 // Write implements io.Writer. 98 func (w *BufferedWriter) Write(b []byte) (int, error) { 99 if len(b) == 0 { 100 return 0, nil 101 } 102 103 w.Lock() 104 defer w.Unlock() 105 106 if !w.buffered { 107 if writer, ok := w.writer.(io.Writer); ok { 108 return writer.Write(b) 109 } 110 } 111 112 totalBytes := 0 113 for len(b) > 0 { 114 if w.buffer == nil { 115 w.buffer = New() 116 } 117 118 nBytes, err := w.buffer.Write(b) 119 totalBytes += nBytes 120 if err != nil { 121 return totalBytes, err 122 } 123 if !w.buffered || w.buffer.IsFull() { 124 if err := w.flushInternal(); err != nil { 125 return totalBytes, err 126 } 127 } 128 b = b[nBytes:] 129 } 130 131 return totalBytes, nil 132 } 133 134 // WriteMultiBuffer implements Writer. It takes ownership of the given MultiBuffer. 135 func (w *BufferedWriter) WriteMultiBuffer(b MultiBuffer) error { 136 if b.IsEmpty() { 137 return nil 138 } 139 140 w.Lock() 141 defer w.Unlock() 142 143 if !w.buffered { 144 return w.writer.WriteMultiBuffer(b) 145 } 146 147 reader := MultiBufferContainer{ 148 MultiBuffer: b, 149 } 150 defer reader.Close() 151 152 for !reader.MultiBuffer.IsEmpty() { 153 if w.buffer == nil { 154 w.buffer = New() 155 } 156 common.Must2(w.buffer.ReadFrom(&reader)) 157 if w.buffer.IsFull() { 158 if err := w.flushInternal(); err != nil { 159 return err 160 } 161 } 162 } 163 164 return nil 165 } 166 167 // Flush flushes buffered content into underlying writer. 168 func (w *BufferedWriter) Flush() error { 169 w.Lock() 170 defer w.Unlock() 171 172 return w.flushInternal() 173 } 174 175 func (w *BufferedWriter) flushInternal() error { 176 if w.buffer.IsEmpty() { 177 return nil 178 } 179 180 b := w.buffer 181 w.buffer = nil 182 183 if writer, ok := w.writer.(io.Writer); ok { 184 err := WriteAllBytes(writer, b.Bytes(), nil) 185 b.Release() 186 return err 187 } 188 189 return w.writer.WriteMultiBuffer(MultiBuffer{b}) 190 } 191 192 // SetBuffered sets whether the internal buffer is used. If set to false, Flush() will be called to clear the buffer. 193 func (w *BufferedWriter) SetBuffered(f bool) error { 194 w.Lock() 195 defer w.Unlock() 196 197 w.buffered = f 198 if !f { 199 return w.flushInternal() 200 } 201 return nil 202 } 203 204 // ReadFrom implements io.ReaderFrom. 205 func (w *BufferedWriter) ReadFrom(reader io.Reader) (int64, error) { 206 if err := w.SetBuffered(false); err != nil { 207 return 0, err 208 } 209 210 var sc SizeCounter 211 err := Copy(NewReader(reader), w, CountSize(&sc)) 212 return sc.Size, err 213 } 214 215 // Close implements io.Closable. 216 func (w *BufferedWriter) Close() error { 217 if err := w.Flush(); err != nil { 218 return err 219 } 220 return common.Close(w.writer) 221 } 222 223 // SequentialWriter is a Writer that writes MultiBuffer sequentially into the underlying io.Writer. 224 type SequentialWriter struct { 225 io.Writer 226 } 227 228 // WriteMultiBuffer implements Writer. 229 func (w *SequentialWriter) WriteMultiBuffer(mb MultiBuffer) error { 230 mb, err := WriteMultiBuffer(w.Writer, mb) 231 ReleaseMulti(mb) 232 return err 233 } 234 235 type noOpWriter byte 236 237 func (noOpWriter) WriteMultiBuffer(b MultiBuffer) error { 238 ReleaseMulti(b) 239 return nil 240 } 241 242 func (noOpWriter) Write(b []byte) (int, error) { 243 return len(b), nil 244 } 245 246 func (noOpWriter) ReadFrom(reader io.Reader) (int64, error) { 247 b := New() 248 defer b.Release() 249 250 totalBytes := int64(0) 251 for { 252 b.Clear() 253 _, err := b.ReadFrom(reader) 254 totalBytes += int64(b.Len()) 255 if err != nil { 256 if errors.Cause(err) == io.EOF { 257 return totalBytes, nil 258 } 259 return totalBytes, err 260 } 261 } 262 } 263 264 var ( 265 // Discard is a Writer that swallows all contents written in. 266 Discard Writer = noOpWriter(0) 267 268 // DiscardBytes is an io.Writer that swallows all contents written in. 269 DiscardBytes io.Writer = noOpWriter(0) 270 )