Code

client: Added support for querying the server version.
[sysdb/go.git] / proto / proto.go
index 7f53f3d82c0732e2b9643f1937e15eb01e113c6e..a58725d6f81a6c7ad451390974e311b63a08b0f7 100644 (file)
@@ -30,7 +30,10 @@ package proto
 
 import (
        "encoding/binary"
+       "encoding/json"
+       "fmt"
        "io"
+       "strings"
 )
 
 // Network byte order.
@@ -77,8 +80,25 @@ const (
        // 'TIMESERIES' command in the server.
        ConnectionTimeseries = Status(7)
 
-       // ConnectionExpr is the internal state for expression parsing.
-       ConnectionExpr = Status(100)
+       // ConnectionMatcher is the internal state for parsing matchers.
+       ConnectionMatcher = Status(100)
+       // ConnectionExpr is the internal state for parsing expressions.
+       ConnectionExpr = Status(101)
+
+       // ConnectionServerVersion is the state requesting the server version.
+       ConnectionServerVersion = Status(1000)
+)
+
+// The DataType describes the type of data in a ConnectionData message.
+type DataType int
+
+const (
+       // A HostList can be unmarshaled to []sysdb.Host.
+       HostList DataType = iota
+       // A Host can be unmarshaled to sysdb.Host.
+       Host
+       // A Timeseries can be unmarshaled to sysdb.Timeseries.
+       Timeseries
 )
 
 // A Message represents a raw message of the SysDB front-end protocol.
@@ -130,4 +150,44 @@ func Write(w io.Writer, m *Message) error {
        return nil
 }
 
+// DataType determines the type of data in a ConnectionData message.
+func (m Message) DataType() (DataType, error) {
+       if m.Type != ConnectionData {
+               return 0, fmt.Errorf("message is not of type DATA")
+       }
+
+       typ := nbo.Uint32(m.Raw[:4])
+       switch Status(typ) {
+       case ConnectionList, ConnectionLookup:
+               return HostList, nil
+       case ConnectionFetch:
+               return Host, nil
+       case ConnectionTimeseries:
+               return Timeseries, nil
+       }
+       return 0, fmt.Errorf("unknown DATA type %d", typ)
+}
+
+// Unmarshal parses the raw body of m and stores the result in the value
+// pointed to by v which has to match the type of the message and its data.
+func Unmarshal(m *Message, v interface{}) error {
+       if m.Type != ConnectionData {
+               return fmt.Errorf("unmarshaling message of type %d not supported", m.Type)
+       }
+       if len(m.Raw) == 0 { // empty command
+               return nil
+       } else if len(m.Raw) < 4 {
+               return fmt.Errorf("DATA message body too short")
+       }
+       return json.Unmarshal(m.Raw[4:], v)
+}
+
+// EscapeString returns the quoted and escaped string s suitable for use
+// in a query.
+func EscapeString(s string) string {
+       // Currently, the server only handles double-quotes.
+       // Backslashes do not serve any special purpose.
+       return "'" + strings.Replace(s, "'", "''", -1) + "'"
+}
+
 // vim: set tw=78 sw=4 sw=4 noexpandtab :