mirror of
https://github.com/mjl-/mox.git
synced 2024-12-27 08:53:48 +03:00
74 lines
1.2 KiB
Go
74 lines
1.2 KiB
Go
|
package moxio
|
||
|
|
||
|
import (
|
||
|
"encoding/base64"
|
||
|
"io"
|
||
|
)
|
||
|
|
||
|
// implement io.Closer
|
||
|
type closerFunc func() error
|
||
|
|
||
|
func (f closerFunc) Close() error {
|
||
|
return f()
|
||
|
}
|
||
|
|
||
|
// Base64Writer turns a writer for data into one that writes base64 content on
|
||
|
// \r\n separated lines of max 78+2 characters length.
|
||
|
func Base64Writer(w io.Writer) io.WriteCloser {
|
||
|
lw := &lineWrapper{w: w}
|
||
|
bw := base64.NewEncoder(base64.StdEncoding, lw)
|
||
|
return struct {
|
||
|
io.Writer
|
||
|
io.Closer
|
||
|
}{
|
||
|
Writer: bw,
|
||
|
Closer: closerFunc(func() error {
|
||
|
if err := bw.Close(); err != nil {
|
||
|
return err
|
||
|
}
|
||
|
return lw.Close()
|
||
|
}),
|
||
|
}
|
||
|
}
|
||
|
|
||
|
type lineWrapper struct {
|
||
|
w io.Writer
|
||
|
n int // Written on current line.
|
||
|
}
|
||
|
|
||
|
func (lw *lineWrapper) Write(buf []byte) (int, error) {
|
||
|
wrote := 0
|
||
|
for len(buf) > 0 {
|
||
|
n := 78 - lw.n
|
||
|
if n > len(buf) {
|
||
|
n = len(buf)
|
||
|
}
|
||
|
nn, err := lw.w.Write(buf[:n])
|
||
|
if nn > 0 {
|
||
|
wrote += nn
|
||
|
buf = buf[nn:]
|
||
|
}
|
||
|
if err != nil {
|
||
|
return wrote, err
|
||
|
}
|
||
|
lw.n += nn
|
||
|
if lw.n == 78 {
|
||
|
_, err := lw.w.Write([]byte("\r\n"))
|
||
|
if err != nil {
|
||
|
return wrote, err
|
||
|
}
|
||
|
lw.n = 0
|
||
|
}
|
||
|
}
|
||
|
return wrote, nil
|
||
|
}
|
||
|
|
||
|
func (lw *lineWrapper) Close() error {
|
||
|
if lw.n > 0 {
|
||
|
lw.n = 0
|
||
|
_, err := lw.w.Write([]byte("\r\n"))
|
||
|
return err
|
||
|
}
|
||
|
return nil
|
||
|
}
|