-
Notifications
You must be signed in to change notification settings - Fork 19
/
writer.go
122 lines (103 loc) · 2.15 KB
/
writer.go
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
package mbox
import (
"bytes"
"errors"
"io"
"time"
)
type messageWriter struct {
w io.Writer
buf bytes.Buffer
}
func (mw *messageWriter) writeLine(l []byte) (int, error) {
if bytes.HasPrefix(l, header) {
if _, err := mw.w.Write([]byte{'>'}); err != nil {
return 0, err
}
}
return mw.w.Write(l)
}
func (mw *messageWriter) Write(p []byte) (int, error) {
mw.buf.Write(p)
b := mw.buf.Bytes()
mw.buf.Reset()
N := 0
for {
i := bytes.IndexByte(b, '\n')
if i < 0 {
n, err := mw.buf.Write(b)
N += n
return N, err
}
var l []byte
l, b = b[:i+1], b[i+1:]
n := len(l)
// Replace CRLF with LF
if len(l) > 1 && l[len(l)-2] == '\r' {
l = l[:len(l)-2]
l = append(l, '\n')
}
_, err := mw.writeLine(l)
N += n
if err != nil {
return N, err
}
}
}
func (mw *messageWriter) Close() error {
b := mw.buf.Bytes()
mw.buf.Reset()
if _, err := mw.writeLine(b); err != nil {
return err
}
_, err := mw.w.Write([]byte("\n\n"))
return err
}
// Writer writes messages to a mbox stream. The Close method must be called to
// end the stream.
type Writer struct {
w io.Writer
last *messageWriter
closed bool
}
// NewWriter creates a new Writer that writes messages to w.
func NewWriter(w io.Writer) *Writer {
return &Writer{w: w}
}
// CreateMessage appends a message to the mbox stream. The message text
// (including both the header and the body) should be written to the returned
// io.Writer.
func (w *Writer) CreateMessage(from string, t time.Time) (io.Writer, error) {
if w.closed {
return nil, errors.New("mbox: Writer.CreateMessage called after Close")
}
if w.last != nil {
if err := w.last.Close(); err != nil {
return nil, err
}
w.last = nil
}
if from == "" {
from = "???@???"
}
if t.IsZero() {
t = time.Now()
}
date := t.UTC().Format(time.ANSIC)
line := "From " + from + " " + date + "\n"
if _, err := io.WriteString(w.w, line); err != nil {
return nil, err
}
w.last = &messageWriter{w: w.w}
return w.last, nil
}
func (w *Writer) Close() error {
if w.closed {
return errors.New("mbox: Writer already closed")
}
w.closed = true
if w.last != nil {
return w.last.Close()
}
return nil
}