package chanio | |
import ( | |
"io" | |
"sync/atomic" | |
) | |
type ChanIO struct { | |
cl atomic.Bool | |
c chan []byte | |
buf []byte | |
} | |
func New() *ChanIO { | |
return &ChanIO{ | |
cl: atomic.Bool{}, | |
c: make(chan []byte), | |
buf: make([]byte, 0), | |
} | |
} | |
func (c *ChanIO) Read(p []byte) (int, error) { | |
if c.cl.Load() { | |
if len(c.buf) == 0 { | |
return 0, io.EOF | |
} | |
n := copy(p, c.buf) | |
if len(c.buf) > n { | |
c.buf = c.buf[n:] | |
} else { | |
c.buf = make([]byte, 0) | |
} | |
return n, nil | |
} | |
for len(c.buf) < len(p) && !c.cl.Load() { | |
c.buf = append(c.buf, <-c.c...) | |
} | |
n := copy(p, c.buf) | |
if len(c.buf) > n { | |
c.buf = c.buf[n:] | |
} else { | |
c.buf = make([]byte, 0) | |
} | |
return n, nil | |
} | |
func (c *ChanIO) Write(p []byte) (int, error) { | |
if c.cl.Load() { | |
return 0, io.ErrClosedPipe | |
} | |
c.c <- p | |
return len(p), nil | |
} | |
func (c *ChanIO) Close() error { | |
if c.cl.Load() { | |
return io.ErrClosedPipe | |
} | |
c.cl.Store(true) | |
close(c.c) | |
return nil | |
} | |