This commit is contained in:
Yangxt
2026-09-21 16:46:55 +08:00
parent 01842c59c6
commit ad2b0a7d3e
58 changed files with 6906 additions and 3 deletions
+116
View File
@@ -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
}