glide setup and dependencies addition
This commit is contained in:
110
vendor/gopkg.in/routeros.v2/proto/reader.go
generated
vendored
Normal file
110
vendor/gopkg.in/routeros.v2/proto/reader.go
generated
vendored
Normal file
@@ -0,0 +1,110 @@
|
||||
package proto
|
||||
|
||||
import (
|
||||
"bufio"
|
||||
"bytes"
|
||||
"fmt"
|
||||
"io"
|
||||
)
|
||||
|
||||
// Reader reads sentences from a RouterOS device.
|
||||
type Reader interface {
|
||||
ReadSentence() (*Sentence, error)
|
||||
}
|
||||
|
||||
type reader struct {
|
||||
*bufio.Reader
|
||||
}
|
||||
|
||||
// NewReader returns a new Reader to read from r.
|
||||
func NewReader(r io.Reader) Reader {
|
||||
return &reader{bufio.NewReader(r)}
|
||||
}
|
||||
|
||||
// ReadSentence reads a sentence.
|
||||
func (r *reader) ReadSentence() (*Sentence, error) {
|
||||
sen := NewSentence()
|
||||
for {
|
||||
b, err := r.readWord()
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
if len(b) == 0 {
|
||||
return sen, nil
|
||||
}
|
||||
// Ex.: !re, !done
|
||||
if sen.Word == "" {
|
||||
sen.Word = string(b)
|
||||
continue
|
||||
}
|
||||
// Command tag.
|
||||
if bytes.HasPrefix(b, []byte(".tag=")) {
|
||||
sen.Tag = string(b[5:])
|
||||
continue
|
||||
}
|
||||
// Ex.: =key=value, =key
|
||||
if bytes.HasPrefix(b, []byte("=")) {
|
||||
t := bytes.SplitN(b[1:], []byte("="), 2)
|
||||
if len(t) == 1 {
|
||||
t = append(t, []byte{})
|
||||
}
|
||||
p := Pair{string(t[0]), string(t[1])}
|
||||
sen.List = append(sen.List, p)
|
||||
sen.Map[p.Key] = p.Value
|
||||
continue
|
||||
}
|
||||
return nil, fmt.Errorf("invalid RouterOS sentence word: %#q", b)
|
||||
}
|
||||
}
|
||||
|
||||
func (r *reader) readNumber(size int) (int64, error) {
|
||||
b := make([]byte, size)
|
||||
_, err := io.ReadFull(r, b)
|
||||
if err != nil {
|
||||
return -1, err
|
||||
}
|
||||
var num int64
|
||||
for _, ch := range b {
|
||||
num = num<<8 | int64(ch)
|
||||
}
|
||||
return num, nil
|
||||
}
|
||||
|
||||
func (r *reader) readLength() (int64, error) {
|
||||
l, err := r.readNumber(1)
|
||||
if err != nil {
|
||||
return -1, err
|
||||
}
|
||||
var n int64
|
||||
switch {
|
||||
case l&0x80 == 0x00:
|
||||
case (l & 0xC0) == 0x80:
|
||||
n, err = r.readNumber(1)
|
||||
l = l & ^0xC0 << 8 | n
|
||||
case l&0xE0 == 0xC0:
|
||||
n, err = r.readNumber(2)
|
||||
l = l & ^0xE0 << 16 | n
|
||||
case l&0xF0 == 0xE0:
|
||||
n, err = r.readNumber(3)
|
||||
l = l & ^0xF0 << 24 | n
|
||||
case l&0xF8 == 0xF0:
|
||||
l, err = r.readNumber(4)
|
||||
}
|
||||
if err != nil {
|
||||
return -1, err
|
||||
}
|
||||
return l, nil
|
||||
}
|
||||
|
||||
func (r *reader) readWord() ([]byte, error) {
|
||||
l, err := r.readLength()
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
b := make([]byte, l)
|
||||
_, err = io.ReadFull(r, b)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return b, nil
|
||||
}
|
||||
28
vendor/gopkg.in/routeros.v2/proto/reader_test.go
generated
vendored
Normal file
28
vendor/gopkg.in/routeros.v2/proto/reader_test.go
generated
vendored
Normal file
@@ -0,0 +1,28 @@
|
||||
package proto
|
||||
|
||||
import (
|
||||
"bytes"
|
||||
"testing"
|
||||
)
|
||||
|
||||
func TestReadLength(t *testing.T) {
|
||||
for _, d := range []struct {
|
||||
length int64
|
||||
rawBytes []byte
|
||||
}{
|
||||
{0x00000001, []byte{0x01}},
|
||||
{0x00000087, []byte{0x80, 0x87}},
|
||||
{0x00004321, []byte{0xC0, 0x43, 0x21}},
|
||||
{0x002acdef, []byte{0xE0, 0x2a, 0xcd, 0xef}},
|
||||
{0x10000080, []byte{0xF0, 0x10, 0x00, 0x00, 0x80}},
|
||||
} {
|
||||
r := NewReader(bytes.NewBuffer(d.rawBytes)).(*reader)
|
||||
l, err := r.readLength()
|
||||
if err != nil {
|
||||
t.Fatalf("readLength error: %s", err)
|
||||
}
|
||||
if l != d.length {
|
||||
t.Fatalf("Expected len=%X for input %#v, got %X", d.length, d.rawBytes, l)
|
||||
}
|
||||
}
|
||||
}
|
||||
26
vendor/gopkg.in/routeros.v2/proto/sentence.go
generated
vendored
Normal file
26
vendor/gopkg.in/routeros.v2/proto/sentence.go
generated
vendored
Normal file
@@ -0,0 +1,26 @@
|
||||
package proto
|
||||
|
||||
import "fmt"
|
||||
|
||||
// Sentence is a line read from a RouterOS device.
|
||||
type Sentence struct {
|
||||
// Word that begins with !
|
||||
Word string
|
||||
Tag string
|
||||
List []Pair
|
||||
Map map[string]string
|
||||
}
|
||||
|
||||
type Pair struct {
|
||||
Key, Value string
|
||||
}
|
||||
|
||||
func NewSentence() *Sentence {
|
||||
return &Sentence{
|
||||
Map: make(map[string]string),
|
||||
}
|
||||
}
|
||||
|
||||
func (sen *Sentence) String() string {
|
||||
return fmt.Sprintf("%s @%s %#q", sen.Word, sen.Tag, sen.List)
|
||||
}
|
||||
42
vendor/gopkg.in/routeros.v2/proto/sentence_test.go
generated
vendored
Normal file
42
vendor/gopkg.in/routeros.v2/proto/sentence_test.go
generated
vendored
Normal file
@@ -0,0 +1,42 @@
|
||||
package proto
|
||||
|
||||
import (
|
||||
"bytes"
|
||||
"fmt"
|
||||
"strings"
|
||||
"testing"
|
||||
)
|
||||
|
||||
func TestReadWrite(t *testing.T) {
|
||||
for i, test := range []struct {
|
||||
in []string
|
||||
out string
|
||||
tag string
|
||||
}{
|
||||
{[]string{"!done"}, `[]`, ""},
|
||||
{[]string{"!done", ".tag=abc123"}, `[]`, "abc123"},
|
||||
{strings.Split("!re =tx-byte=123456789 =only-key", " "), "[{`tx-byte` `123456789`} {`only-key` ``}]", ""},
|
||||
} {
|
||||
buf := &bytes.Buffer{}
|
||||
// Write sentence into buf.
|
||||
w := NewWriter(buf)
|
||||
for _, word := range test.in {
|
||||
w.WriteWord(word)
|
||||
}
|
||||
w.WriteWord("")
|
||||
// Read sentence from buf.
|
||||
r := NewReader(buf)
|
||||
sen, err := r.ReadSentence()
|
||||
if err != nil {
|
||||
t.Errorf("#%d: Input(%#q)=%#v", i, test.in, err)
|
||||
continue
|
||||
}
|
||||
x := fmt.Sprintf("%#q", sen.List)
|
||||
if x != test.out {
|
||||
t.Errorf("#%d: Input(%#q)=%s; want %s", i, test.in, x, test.out)
|
||||
}
|
||||
if sen.Tag != test.tag {
|
||||
t.Errorf("#%d: Input(%#q)=%s; want %s", i, test.in, sen.Tag, test.tag)
|
||||
}
|
||||
}
|
||||
}
|
||||
82
vendor/gopkg.in/routeros.v2/proto/writer.go
generated
vendored
Normal file
82
vendor/gopkg.in/routeros.v2/proto/writer.go
generated
vendored
Normal file
@@ -0,0 +1,82 @@
|
||||
package proto
|
||||
|
||||
import (
|
||||
"bufio"
|
||||
"io"
|
||||
"sync"
|
||||
)
|
||||
|
||||
// Writer writes words to a RouterOS device.
|
||||
type Writer interface {
|
||||
BeginSentence()
|
||||
WriteWord(word string)
|
||||
EndSentence() error
|
||||
}
|
||||
|
||||
type writer struct {
|
||||
*bufio.Writer
|
||||
err error
|
||||
sync.Mutex
|
||||
}
|
||||
|
||||
// NewWriter returns a new Writer to write to w.
|
||||
func NewWriter(w io.Writer) Writer {
|
||||
return &writer{Writer: bufio.NewWriter(w)}
|
||||
}
|
||||
|
||||
// BeginSentence prepares w for writing a sentence.
|
||||
func (w *writer) BeginSentence() {
|
||||
w.Lock()
|
||||
}
|
||||
|
||||
// EndSentence writes the end-of-sentence marker (an empty word).
|
||||
// It returns the first error that occurred on calls to methods on w.
|
||||
func (w *writer) EndSentence() error {
|
||||
w.WriteWord("")
|
||||
w.flush()
|
||||
err := w.err
|
||||
w.Unlock()
|
||||
return err
|
||||
}
|
||||
|
||||
// WriteWord writes one word.
|
||||
func (w *writer) WriteWord(word string) {
|
||||
b := []byte(word)
|
||||
w.write(encodeLength(len(b)))
|
||||
w.write(b)
|
||||
}
|
||||
|
||||
func (w *writer) flush() {
|
||||
if w.err != nil {
|
||||
return
|
||||
}
|
||||
err := w.Flush()
|
||||
if err != nil {
|
||||
w.err = err
|
||||
}
|
||||
}
|
||||
|
||||
func (w *writer) write(b []byte) {
|
||||
if w.err != nil {
|
||||
return
|
||||
}
|
||||
_, err := w.Write(b)
|
||||
if err != nil {
|
||||
w.err = err
|
||||
}
|
||||
}
|
||||
|
||||
func encodeLength(l int) []byte {
|
||||
switch {
|
||||
case l < 0x80:
|
||||
return []byte{byte(l)}
|
||||
case l < 0x4000:
|
||||
return []byte{byte(l>>8) | 0x80, byte(l)}
|
||||
case l < 0x200000:
|
||||
return []byte{byte(l>>16) | 0xC0, byte(l >> 8), byte(l)}
|
||||
case l < 0x10000000:
|
||||
return []byte{byte(l>>24) | 0xE0, byte(l >> 16), byte(l >> 8), byte(l)}
|
||||
default:
|
||||
return []byte{0xF0, byte(l >> 24), byte(l >> 16), byte(l >> 8), byte(l)}
|
||||
}
|
||||
}
|
||||
24
vendor/gopkg.in/routeros.v2/proto/writer_test.go
generated
vendored
Normal file
24
vendor/gopkg.in/routeros.v2/proto/writer_test.go
generated
vendored
Normal file
@@ -0,0 +1,24 @@
|
||||
package proto
|
||||
|
||||
import (
|
||||
"bytes"
|
||||
"testing"
|
||||
)
|
||||
|
||||
func TestEncodeLength(t *testing.T) {
|
||||
for _, d := range []struct {
|
||||
length int
|
||||
rawBytes []byte
|
||||
}{
|
||||
{0x00000001, []byte{0x01}},
|
||||
{0x00000087, []byte{0x80, 0x87}},
|
||||
{0x00004321, []byte{0xC0, 0x43, 0x21}},
|
||||
{0x002acdef, []byte{0xE0, 0x2a, 0xcd, 0xef}},
|
||||
{0x10000080, []byte{0xF0, 0x10, 0x00, 0x00, 0x80}},
|
||||
} {
|
||||
b := encodeLength(d.length)
|
||||
if bytes.Compare(b, d.rawBytes) != 0 {
|
||||
t.Fatalf("Expected output %#v for len=%d, got %#v", d.rawBytes, d.length, b)
|
||||
}
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user