aim-oscar-server/oscar/buf.go
2021-12-18 21:02:47 -05:00

128 lines
2.5 KiB
Go

package oscar
import (
"aim-oscar/util"
"encoding"
"encoding/binary"
"io"
)
// Buffer is a handy byte slice that reads from the front and writes on the end
type Buffer struct {
d []byte
}
// Seek moves the read cursor forward. If the cursor is beyond the length of the byte
// slice then the buffer slice is just replaced with an empty slice
func (b *Buffer) Seek(n int) {
if n > len(b.d) {
b.d = make([]byte, 0)
return
}
b.d = b.d[n:]
}
func (b *Buffer) Read(d []byte) (int, error) {
if len(d) > len(b.d) {
return 0, io.EOF
}
n := copy(d, b.d[0:len(d)])
return n, nil
}
func (b *Buffer) ReadUint8() (uint8, error) {
if len(b.d) < 1 {
return 0, io.EOF
}
ret := uint8(b.d[0])
b.d = b.d[1:]
return ret, nil
}
func (b *Buffer) ReadUint16() (uint16, error) {
if len(b.d) < 2 {
return 0, io.EOF
}
ret := binary.BigEndian.Uint16(b.d[0:2])
b.d = b.d[2:]
return ret, nil
}
func (b *Buffer) ReadUint32() (uint32, error) {
if len(b.d) < 4 {
return 0, io.EOF
}
ret := binary.BigEndian.Uint32(b.d[0:4])
b.d = b.d[4:]
return ret, nil
}
func (b *Buffer) ReadUint64() (uint64, error) {
if len(b.d) < 8 {
return 0, io.EOF
}
ret := binary.BigEndian.Uint64(b.d[0:8])
b.d = b.d[8:]
return ret, nil
}
// ReadLPString reads a length-prefixed string. The first byte should be the string length
// followed by that many bytes. Returns io.EOF if there are less bytes than indicated.
func (b *Buffer) ReadLPString() (string, error) {
length, err := b.ReadUint8()
if err != nil {
return "", nil
}
if len(b.d) < int(length) {
return "", io.EOF
}
str := string(b.d[:length])
b.d = b.d[length:]
return str, nil
}
func (b *Buffer) WriteUint8(x uint8) {
b.d = append(b.d, x)
}
func (b *Buffer) WriteUint16(x uint16) {
b.d = append(b.d, 0, 0)
binary.BigEndian.PutUint16(b.d[len(b.d)-2:], x)
}
func (b *Buffer) WriteUint32(x uint32) {
b.d = append(b.d, 0, 0, 0, 0)
binary.BigEndian.PutUint32(b.d[len(b.d)-4:], x)
}
func (b *Buffer) WriteUint64(x uint64) {
b.d = append(b.d, 0, 0, 0, 0, 0, 0, 0, 0)
binary.BigEndian.PutUint64(b.d[len(b.d)-8:], x)
}
func (b *Buffer) WriteString(x string) {
b.d = append(b.d, []byte(x)...)
}
func (b *Buffer) WriteLPString(x string) {
b.WriteUint8(uint8(len(x)))
b.WriteString(x)
}
func (b *Buffer) Write(x []byte) (int, error) {
b.d = append(b.d, x...)
return len(x), nil
}
func (b *Buffer) WriteBinary(e encoding.BinaryMarshaler) {
d, err := e.MarshalBinary()
util.PanicIfError(err)
b.d = append(b.d, d...)
}
func (b *Buffer) Bytes() []byte {
return b.d
}