README
¶
Protobytes
Protobytes is a Go library inspired by Rust's crate bytes. It provides a series of methods for big-endian and little-endian number operations, as well as a helper for io.Reader
.
Purpose
The goal of this library is to provide an easy-to-use bytes.Buffer
. However, it has been split into BytesReader
and BytesWriter
, which perform similarly to using bytes.Buffer
directly.
When using bytes.Buffer
, binary.Write
has poor performance and unnecessary allocation. Instead, you can use the methods provided by protobytes.
Usage
BytesReader
and BytesWriter
are similar to bytes.Buffer
, but they are not thread-safe. bytes.Buffer
, binary.Write
and []byte
conversion is very easy and cheap.
buf := make([]byte, 0, 1024)
w := BytesWriter(buf)
w.ReadFull(rand.Reader, 64)
w.PutUint8(0x01)
w.PutUint16be(0x0203)
r := BytesReader(w.Bytes())
randomBytes, r := r.SplitAt(64) // split to two BytesReader
r.ReadUint8() // auto step forward
r.ReadUint16be()
example for parse proxy protocol v2 using BytesReader
:
hexStr := "0d0a0d0a000d0a515549540a20120c000c22384eac10000104d21f90"
buf, _ := hex.DecodeString(hexStr)
r := BytesReader(buf)
if r.Len() < 16 {
panic("short buffer")
}
sign, r := r.SplitAt(12)
if !bytes.Equal(signature, sign) {
panic("invalid signature")
}
header := &Header{}
switch command := r.ReadUint8(); command {
case LOCAL, PROXY:
header.Command = command
default:
panic(fmt.Errorf("invalid command %x", command))
}
switch protocol := r.ReadUint8(); protocol {
case UNSPEC, TCPOverIPv4, UDPOverIPv4, TCPOverIPv6, UDPOverIPv6, UNIXStream, UNIXDatagram:
header.TransportProtocol = protocol
default:
panic(fmt.Errorf("invalid protocol %x", protocol))
}
length := r.ReadUint16le()
switch length {
case lengthIPv4, lengthIPv6, lengthUnix:
default:
panic(fmt.Errorf("invalid length %x", length))
}
if r.Len() < int(length) {
panic("short buffer")
}
switch length {
case lengthIPv4:
srcAddr := r.ReadIPv4()
dstAddr := r.ReadIPv4()
srcPort := r.ReadUint16be()
dstPort := r.ReadUint16be()
header.SourceAddr = netip.AddrPortFrom(srcAddr, srcPort)
header.DestinationAddr = netip.AddrPortFrom(dstAddr, dstPort)
case lengthIPv6:
srcAddr := r.ReadIPv6()
dstAddr := r.ReadIPv6()
srcPort := r.ReadUint16be()
dstPort := r.ReadUint16be()
header.SourceAddr = netip.AddrPortFrom(srcAddr, srcPort)
header.DestinationAddr = netip.AddrPortFrom(dstAddr, dstPort)
default:
panic(fmt.Errorf("unsupported protocol %x", length))
}
fmt.Printf("%+v\n", header)
Documentation
¶
Index ¶
- type BytesReader
- func (b *BytesReader) Cap() int
- func (b *BytesReader) IsEmpty() bool
- func (b *BytesReader) Len() int
- func (b *BytesReader) Read(p []byte) (n int, err error)
- func (b *BytesReader) ReadByte() (byte, error)
- func (b *BytesReader) ReadIPv4() netip.Addr
- func (b *BytesReader) ReadIPv6() netip.Addr
- func (b *BytesReader) ReadUint16be() uint16
- func (b *BytesReader) ReadUint16le() uint16
- func (b *BytesReader) ReadUint32be() uint32
- func (b *BytesReader) ReadUint32le() uint32
- func (b *BytesReader) ReadUint64be() uint64
- func (b *BytesReader) ReadUint64le() uint64
- func (b *BytesReader) ReadUint8() uint8
- func (b *BytesReader) ReadUvarint() (uint64, error)
- func (b *BytesReader) ReadVarint() (int64, error)
- func (b *BytesReader) Skip(n int)
- func (b *BytesReader) SplitAt(n int) (BytesReader, BytesReader)
- func (b *BytesReader) SplitBy(f func(byte) bool) (BytesReader, BytesReader)
- type BytesWriter
- func (b *BytesWriter) Bytes() []byte
- func (b *BytesWriter) Cap() int
- func (b *BytesWriter) Grow(n int) int
- func (b *BytesWriter) Len() int
- func (b *BytesWriter) PutRune(r rune)
- func (b *BytesWriter) PutSlice(p []byte)
- func (b *BytesWriter) PutString(s string)
- func (b *BytesWriter) PutUint16be(v uint16)
- func (b *BytesWriter) PutUint16le(v uint16)
- func (b *BytesWriter) PutUint32be(v uint32)
- func (b *BytesWriter) PutUint32le(v uint32)
- func (b *BytesWriter) PutUint64be(v uint64)
- func (b *BytesWriter) PutUint64le(v uint64)
- func (b *BytesWriter) PutUint8(v uint8)
- func (b *BytesWriter) PutUvarint(v uint64)
- func (b *BytesWriter) PutVarint(v int64)
- func (b *BytesWriter) ReadFull(reader io.Reader, n int) error
- func (b *BytesWriter) Reset()
- func (b *BytesWriter) Slice(start, end int) BytesWriter
- func (b *BytesWriter) Write(p []byte) (n int, err error)
- type Reader
- func (p *Reader) Buffered() int
- func (p *Reader) Error() error
- func (p *Reader) Next(n int) (BytesReader, error)
- func (p *Reader) Read(buf []byte) (n int, err error)
- func (p *Reader) ReadFull(buf []byte) (err error)
- func (p *Reader) Reset(reader io.Reader)
- func (p *Reader) TryByte() (b byte)
- func (p *Reader) TryNext(n int) BytesReader
- func (p *Reader) TryPeekUint16be() (i uint16)
- func (p *Reader) TryPeekUint16le() (i uint16)
- func (p *Reader) TryPeekUint32be() (i uint32)
- func (p *Reader) TryPeekUint32le() (i uint32)
- func (p *Reader) TryPeekUint64be() (i uint64)
- func (p *Reader) TryPeekUint64le() (i uint64)
- func (p *Reader) TryPeekUint8() (i uint8)
- func (p *Reader) TryReadFull(buf []byte)
- func (p *Reader) TryReadUint16be() (i uint16)
- func (p *Reader) TryReadUint16le() (i uint16)
- func (p *Reader) TryReadUint32be() (i uint32)
- func (p *Reader) TryReadUint32le() (i uint32)
- func (p *Reader) TryReadUint64be() (i uint64)
- func (p *Reader) TryReadUint64le() (i uint64)
- func (p *Reader) TryReadUint8() (i uint8)
Examples ¶
Constants ¶
This section is empty.
Variables ¶
This section is empty.
Functions ¶
This section is empty.
Types ¶
type BytesReader ¶
type BytesReader []byte
BytesReader is a wrapper for a byte slice that provides helper methods for reading various types of data from the slice.
func (*BytesReader) Cap ¶
func (b *BytesReader) Cap() int
Cap returns the capacity of the byte slice.
func (*BytesReader) IsEmpty ¶
func (b *BytesReader) IsEmpty() bool
IsEmpty checks if the byte slice is empty.
func (*BytesReader) Read ¶
func (b *BytesReader) Read(p []byte) (n int, err error)
Read reads up to len(p) bytes from the byte slice and skips len(p) bytes. implements io.Reader. If the buffer has no data to return, err is io.EOF (unless len(p) is zero); otherwise it is nil.
func (*BytesReader) ReadByte ¶
func (b *BytesReader) ReadByte() (byte, error)
ReadByte implements io.ByteReader.
func (*BytesReader) ReadIPv4 ¶
func (b *BytesReader) ReadIPv4() netip.Addr
ReadIPv4 reads a net.IPAddr with an IPv4 address.
func (*BytesReader) ReadIPv6 ¶
func (b *BytesReader) ReadIPv6() netip.Addr
ReadIPv6 reads a net.IPAddr with an IPv6 address.
func (*BytesReader) ReadUint16be ¶
func (b *BytesReader) ReadUint16be() uint16
ReadUint16be reads a uint16 value in big endian from the byte slice and skips 2 bytes.
func (*BytesReader) ReadUint16le ¶
func (b *BytesReader) ReadUint16le() uint16
ReadUint16le reads a uint16 value in little endian from the byte slice and skips 2 bytes.
func (*BytesReader) ReadUint32be ¶
func (b *BytesReader) ReadUint32be() uint32
ReadUint32be reads a uint32 value in big endian from the byte slice and skips 4 bytes.
func (*BytesReader) ReadUint32le ¶
func (b *BytesReader) ReadUint32le() uint32
ReadUint32le reads a uint32 value in little endian from the byte slice and skips 4 bytes.
func (*BytesReader) ReadUint64be ¶
func (b *BytesReader) ReadUint64be() uint64
ReadUint64be reads a uint64 value in big endian from the byte slice and skips 8 bytes.
func (*BytesReader) ReadUint64le ¶
func (b *BytesReader) ReadUint64le() uint64
ReadUint64le reads a uint64 value in little endian from the byte slice and skips 8 bytes.
func (*BytesReader) ReadUint8 ¶
func (b *BytesReader) ReadUint8() uint8
ReadUint8 reads a uint8 value from the byte slice and skips 1 byte.
func (*BytesReader) ReadUvarint ¶
func (b *BytesReader) ReadUvarint() (uint64, error)
ReadUvarint read Uvarint from the byte slice. it return error because of the length of the byte slice can't be sure.
func (*BytesReader) ReadVarint ¶
func (b *BytesReader) ReadVarint() (int64, error)
ReadVarint read Varint from the byte slice. it return error because of the length of the byte slice can't be sure.
func (*BytesReader) SplitAt ¶
func (b *BytesReader) SplitAt(n int) (BytesReader, BytesReader)
SplitAt splits the byte slice at the given index and returns two new BytesReader.
func (*BytesReader) SplitBy ¶
func (b *BytesReader) SplitBy(f func(byte) bool) (BytesReader, BytesReader)
SplitBy splits the byte slice by a given function and returns two new BytesReader.
type BytesWriter ¶
type BytesWriter []byte
func (*BytesWriter) Bytes ¶
func (b *BytesWriter) Bytes() []byte
func (*BytesWriter) Cap ¶
func (b *BytesWriter) Cap() int
Cap returns the capacity of the byte slice.
func (*BytesWriter) Grow ¶
func (b *BytesWriter) Grow(n int) int
Grow grows the buffer's capacity. It returns the index where bytes should be written.
func (*BytesWriter) Len ¶
func (b *BytesWriter) Len() int
func (*BytesWriter) PutRune ¶
func (b *BytesWriter) PutRune(r rune)
func (*BytesWriter) PutSlice ¶
func (b *BytesWriter) PutSlice(p []byte)
func (*BytesWriter) PutString ¶
func (b *BytesWriter) PutString(s string)
func (*BytesWriter) PutUint16be ¶
func (b *BytesWriter) PutUint16be(v uint16)
func (*BytesWriter) PutUint16le ¶
func (b *BytesWriter) PutUint16le(v uint16)
func (*BytesWriter) PutUint32be ¶
func (b *BytesWriter) PutUint32be(v uint32)
func (*BytesWriter) PutUint32le ¶
func (b *BytesWriter) PutUint32le(v uint32)
func (*BytesWriter) PutUint64be ¶
func (b *BytesWriter) PutUint64be(v uint64)
func (*BytesWriter) PutUint64le ¶
func (b *BytesWriter) PutUint64le(v uint64)
func (*BytesWriter) PutUint8 ¶
func (b *BytesWriter) PutUint8(v uint8)
func (*BytesWriter) PutUvarint ¶
func (b *BytesWriter) PutUvarint(v uint64)
func (*BytesWriter) PutVarint ¶
func (b *BytesWriter) PutVarint(v int64)
func (*BytesWriter) Reset ¶
func (b *BytesWriter) Reset()
func (*BytesWriter) Slice ¶
func (b *BytesWriter) Slice(start, end int) BytesWriter
type Reader ¶
type Reader struct {
// contains filtered or unexported fields
}
func (*Reader) TryNext ¶
func (p *Reader) TryNext(n int) BytesReader