app-init
This commit is contained in:
@@ -0,0 +1,116 @@
|
||||
package navicat
|
||||
|
||||
import (
|
||||
"encoding/binary"
|
||||
"fmt"
|
||||
"io"
|
||||
)
|
||||
|
||||
type reader struct {
|
||||
buf []byte
|
||||
off int
|
||||
}
|
||||
|
||||
func newReader(b []byte) *reader {
|
||||
return &reader{buf: b}
|
||||
}
|
||||
|
||||
func (r *reader) remaining() int {
|
||||
return len(r.buf) - r.off
|
||||
}
|
||||
|
||||
func (r *reader) peek() (byte, error) {
|
||||
if r.off >= len(r.buf) {
|
||||
return 0, io.EOF
|
||||
}
|
||||
return r.buf[r.off], nil
|
||||
}
|
||||
|
||||
func (r *reader) readByte() (byte, error) {
|
||||
if r.off >= len(r.buf) {
|
||||
return 0, io.ErrUnexpectedEOF
|
||||
}
|
||||
b := r.buf[r.off]
|
||||
r.off++
|
||||
return b, nil
|
||||
}
|
||||
|
||||
func (r *reader) readN(n int) ([]byte, error) {
|
||||
if n < 0 {
|
||||
return nil, fmt.Errorf("negative length")
|
||||
}
|
||||
if r.off+n > len(r.buf) {
|
||||
return nil, io.ErrUnexpectedEOF
|
||||
}
|
||||
s := r.buf[r.off : r.off+n]
|
||||
r.off += n
|
||||
return s, nil
|
||||
}
|
||||
|
||||
func (r *reader) u16() (uint16, error) {
|
||||
b, err := r.readN(2)
|
||||
if err != nil {
|
||||
return 0, err
|
||||
}
|
||||
return binary.BigEndian.Uint16(b), nil
|
||||
}
|
||||
|
||||
func (r *reader) u32() (uint32, error) {
|
||||
b, err := r.readN(4)
|
||||
if err != nil {
|
||||
return 0, err
|
||||
}
|
||||
return binary.BigEndian.Uint32(b), nil
|
||||
}
|
||||
|
||||
// block reads GetBlock. nullable allows 0xFF as SQL NULL (EchoData only).
|
||||
func (r *reader) block(nullable bool) (val []byte, isNull bool, err error) {
|
||||
if r.off >= len(r.buf) {
|
||||
return nil, false, io.ErrUnexpectedEOF
|
||||
}
|
||||
first := r.buf[r.off]
|
||||
if nullable && first == markNull {
|
||||
r.off++
|
||||
return nil, true, nil
|
||||
}
|
||||
r.off++
|
||||
var n int
|
||||
if first < 254 {
|
||||
n = int(first)
|
||||
} else if first == markLong {
|
||||
ln, err := r.u32()
|
||||
if err != nil {
|
||||
return nil, false, err
|
||||
}
|
||||
if ln > 64<<20 {
|
||||
return nil, false, fmt.Errorf("block length %d exceeds 64MiB limit", ln)
|
||||
}
|
||||
n = int(ln)
|
||||
} else {
|
||||
return nil, false, fmt.Errorf("invalid block marker 0x%02x", first)
|
||||
}
|
||||
b, err := r.readN(n)
|
||||
if err != nil {
|
||||
return nil, false, err
|
||||
}
|
||||
return b, false, nil
|
||||
}
|
||||
|
||||
func (r *reader) blockBytes() ([]byte, error) {
|
||||
b, isNull, err := r.block(false)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
if isNull {
|
||||
return nil, fmt.Errorf("unexpected NULL block")
|
||||
}
|
||||
return b, nil
|
||||
}
|
||||
|
||||
func (r *reader) blockString() (string, error) {
|
||||
b, err := r.blockBytes()
|
||||
if err != nil {
|
||||
return "", err
|
||||
}
|
||||
return string(b), nil
|
||||
}
|
||||
Reference in New Issue
Block a user