Implement a proper io.Reader interface since the current implementation is flawed

This commit is contained in:
Winni Neessen 2022-10-20 15:52:53 +02:00
parent 50ee227456
commit 966615584d
Signed by: wneessen
GPG key ID: 5F3AF39B820C119D
2 changed files with 53 additions and 0 deletions

20
msg.go
View file

@ -807,6 +807,26 @@ func (m *Msg) WriteToSendmailWithContext(ctx context.Context, sp string, a ...st
return nil
}
// NewReader returns a Msg reader that satisfies the io.Reader interface.
// **Please note:** when creating a new reader, the current state of the Msg is taken, as
// basis for the reader. If you perform changes on Msg after creating the reader, you need
// to perform a call to Msg.UpdateReader first
func (m *Msg) NewReader() io.Reader {
wbuf := bytes.Buffer{}
_, _ = m.Write(&wbuf)
r := &reader{buf: wbuf.Bytes()}
return r
}
// UpdateReader will update a reader with the content of the current Msg and reset the reader position
// to the start
func (m *Msg) UpdateReader(r *reader) {
wbuf := bytes.Buffer{}
_, _ = m.Write(&wbuf)
r.Reset()
r.buf = wbuf.Bytes()
}
// Read outputs the length of p into p to satisfy the io.Reader interface
func (m *Msg) Read(p []byte) (int, error) {
wbuf := bytes.Buffer{}

33
reader.go Normal file
View file

@ -0,0 +1,33 @@
package mail
import "io"
// reader is a type that implements the io.Reader interface for a Msg
type reader struct {
buf []byte // contents are the bytes buf[off : len(buf)]
off int // read at &buf[off], write at &buf[len(buf)]
}
// Read reads the length of p of the Msg buffer to satisfy the io.Reader interface
func (r *reader) Read(p []byte) (n int, err error) {
if r.empty() {
r.Reset()
if len(p) == 0 {
return 0, nil
}
return 0, io.EOF
}
n = copy(p, r.buf[r.off:])
r.off += n
return n, nil
}
// Reset resets the Reader buffer to be empty, but it retains the underlying storage
// for use by future writes.
func (r *reader) Reset() {
r.buf = r.buf[:0]
r.off = 0
}
// empty reports whether the unread portion of the Reader buffer is empty.
func (r *reader) empty() bool { return len(r.buf) <= r.off }