summaryrefslogtreecommitdiffstats
path: root/vendor/github.com/sorcix/irc/stream.go
diff options
context:
space:
mode:
Diffstat (limited to 'vendor/github.com/sorcix/irc/stream.go')
-rw-r--r--vendor/github.com/sorcix/irc/stream.go134
1 files changed, 134 insertions, 0 deletions
diff --git a/vendor/github.com/sorcix/irc/stream.go b/vendor/github.com/sorcix/irc/stream.go
new file mode 100644
index 00000000..c4af9af1
--- /dev/null
+++ b/vendor/github.com/sorcix/irc/stream.go
@@ -0,0 +1,134 @@
+// Copyright 2014 Vic Demuzere
+//
+// Use of this source code is governed by the MIT license.
+
+package irc
+
+import (
+ "bufio"
+ "io"
+ "net"
+ "sync"
+)
+
+// Messages are delimited with CR and LF line endings,
+// we're using the last one to split the stream. Both are removed
+// during message parsing.
+const delim byte = '\n'
+
+var endline = []byte("\r\n")
+
+// A Conn represents an IRC network protocol connection.
+// It consists of an Encoder and Decoder to manage I/O.
+type Conn struct {
+ Encoder
+ Decoder
+
+ conn io.ReadWriteCloser
+}
+
+// NewConn returns a new Conn using rwc for I/O.
+func NewConn(rwc io.ReadWriteCloser) *Conn {
+ return &Conn{
+ Encoder: Encoder{
+ writer: rwc,
+ },
+ Decoder: Decoder{
+ reader: bufio.NewReader(rwc),
+ },
+ conn: rwc,
+ }
+}
+
+// Dial connects to the given address using net.Dial and
+// then returns a new Conn for the connection.
+func Dial(addr string) (*Conn, error) {
+ c, err := net.Dial("tcp", addr)
+
+ if err != nil {
+ return nil, err
+ }
+
+ return NewConn(c), nil
+}
+
+// Close closes the underlying ReadWriteCloser.
+func (c *Conn) Close() error {
+ return c.conn.Close()
+}
+
+// A Decoder reads Message objects from an input stream.
+type Decoder struct {
+ reader *bufio.Reader
+ line string
+ mu sync.Mutex
+}
+
+// NewDecoder returns a new Decoder that reads from r.
+func NewDecoder(r io.Reader) *Decoder {
+ return &Decoder{
+ reader: bufio.NewReader(r),
+ }
+}
+
+// Decode attempts to read a single Message from the stream.
+//
+// Returns a non-nil error if the read failed.
+func (dec *Decoder) Decode() (m *Message, err error) {
+
+ dec.mu.Lock()
+ dec.line, err = dec.reader.ReadString(delim)
+ dec.mu.Unlock()
+
+ if err != nil {
+ return nil, err
+ }
+
+ return ParseMessage(dec.line), nil
+}
+
+// An Encoder writes Message objects to an output stream.
+type Encoder struct {
+ writer io.Writer
+ mu sync.Mutex
+}
+
+// NewEncoder returns a new Encoder that writes to w.
+func NewEncoder(w io.Writer) *Encoder {
+ return &Encoder{
+ writer: w,
+ }
+}
+
+// Encode writes the IRC encoding of m to the stream.
+//
+// This method may be used from multiple goroutines.
+//
+// Returns an non-nil error if the write to the underlying stream stopped early.
+func (enc *Encoder) Encode(m *Message) (err error) {
+
+ _, err = enc.Write(m.Bytes())
+
+ return
+}
+
+// Write writes len(p) bytes from p followed by CR+LF.
+//
+// This method can be used simultaneously from multiple goroutines,
+// it guarantees to serialize access. However, writing a single IRC message
+// using multiple Write calls will cause corruption.
+func (enc *Encoder) Write(p []byte) (n int, err error) {
+
+ enc.mu.Lock()
+ n, err = enc.writer.Write(p)
+
+ if err != nil {
+ enc.mu.Unlock()
+ return
+ }
+
+ _, err = enc.writer.Write(endline)
+ enc.mu.Unlock()
+
+ return
+}