1package imapclient
2
3import (
4 "io"
5 "net"
6)
7
8// prefixConn is a net.Conn with a buffer from which the first reads are satisfied.
9// used for STARTTLS where already did a buffered read of initial TLS data.
10type prefixConn struct {
11 prefix []byte
12 net.Conn
13}
14
15func (c *prefixConn) Read(buf []byte) (int, error) {
16 if len(c.prefix) > 0 {
17 n := len(buf)
18 if n > len(c.prefix) {
19 n = len(c.prefix)
20 }
21 copy(buf[:n], c.prefix[:n])
22 c.prefix = c.prefix[n:]
23 if len(c.prefix) == 0 {
24 c.prefix = nil
25 }
26 return n, nil
27 }
28 return c.Conn.Read(buf)
29}
30
31// xprefixConn checks if there are any buffered unconsumed reads. If not, it
32// returns c.conn. Otherwise, it returns a *prefixConn from which the buffered data
33// can be read followed by data from c.conn.
34func (c *Conn) xprefixConn() net.Conn {
35 n := c.br.Buffered()
36 if n == 0 {
37 return c.conn
38 }
39
40 buf := make([]byte, n)
41 _, err := io.ReadFull(c.br, buf)
42 c.xcheckf(err, "get buffered data")
43 return &prefixConn{buf, c.conn}
44}
45