mirror of
https://github.com/SagerNet/sing.git
synced 2025-04-03 20:07:38 +03:00
83 lines
1.4 KiB
Go
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
|
|
}
|