sing/common/bufio/buffer.go
2024-06-24 09:42:23 +08:00

83 lines
1.4 KiB
Go

package bufio
import (
"io"
"sync"
"github.com/sagernet/sing/common"
"github.com/sagernet/sing/common/buf"
)
type BufferedWriter struct {
upstream io.Writer
buffer *buf.Buffer
access sync.Mutex
}
func NewBufferedWriter(upstream io.Writer, buffer *buf.Buffer) *BufferedWriter {
return &BufferedWriter{
upstream: upstream,
buffer: buffer,
}
}
func (w *BufferedWriter) Write(p []byte) (n int, err error) {
w.access.Lock()
defer w.access.Unlock()
if w.buffer == nil {
return w.upstream.Write(p)
}
for {
var writeN int
writeN, err = w.buffer.Write(p[n:])
n += writeN
if n == len(p) {
return
}
_, err = w.upstream.Write(w.buffer.Bytes())
if err != nil {
return
}
w.buffer.Reset()
}
}
func (w *BufferedWriter) WriteByte(c byte) error {
w.access.Lock()
defer w.access.Unlock()
if w.buffer == nil {
return common.Error(w.upstream.Write([]byte{c}))
}
for {
err := w.buffer.WriteByte(c)
if err == nil {
return nil
}
_, err = w.upstream.Write(w.buffer.Bytes())
if err != nil {
return err
}
w.buffer.Reset()
}
}
func (w *BufferedWriter) Fallthrough() error {
w.access.Lock()
defer w.access.Unlock()
if w.buffer == nil {
return nil
}
if !w.buffer.IsEmpty() {
_, err := w.upstream.Write(w.buffer.Bytes())
if err != nil {
return err
}
}
w.buffer.Release()
w.buffer = nil
return nil
}
func (w *BufferedWriter) WriterReplaceable() bool {
return w.buffer == nil
}