222 lines
4.5 KiB
Go
222 lines
4.5 KiB
Go
// Package bread is a set of helper functions for reading bytes into different types from a buffer.
|
|
package bread
|
|
|
|
import (
|
|
"bytes"
|
|
"fmt"
|
|
"math"
|
|
"time"
|
|
)
|
|
|
|
// Read bytes buffer and return byte
|
|
func Byte(buf *bytes.Buffer) (byte, error) {
|
|
if err := checkLength(buf, 1); err != nil {
|
|
return 0, err
|
|
}
|
|
|
|
return buf.ReadByte()
|
|
}
|
|
|
|
// Read bytes buffer and return boolean, where 1 is true, 0 is false, other error
|
|
func Bool(buf *bytes.Buffer) (bool, error) {
|
|
value, err := Byte(buf)
|
|
if err != nil {
|
|
return false, err
|
|
}
|
|
|
|
switch value {
|
|
case 1:
|
|
return true, nil
|
|
case 0:
|
|
return false, nil
|
|
default:
|
|
return false, fmt.Errorf("%w: 0x%X", ErrBool, value)
|
|
}
|
|
}
|
|
|
|
// Read bytes buffer and return int8
|
|
func Int8(buf *bytes.Buffer) (int8, error) {
|
|
value, err := Byte(buf)
|
|
if err != nil {
|
|
return 0, err
|
|
}
|
|
|
|
return int8(value), nil
|
|
}
|
|
|
|
// Read bytes buffer and return int16
|
|
func Int16(buf *bytes.Buffer) (int16, error) {
|
|
var value int16
|
|
if err := readNumber(buf, &value, 2); err != nil {
|
|
return 0, err
|
|
}
|
|
|
|
return value, nil
|
|
}
|
|
|
|
// Read bytes buffer and return int32
|
|
func Int32(buf *bytes.Buffer) (int32, error) {
|
|
var value int32
|
|
if err := readNumber(buf, &value, 4); err != nil {
|
|
return 0, err
|
|
}
|
|
|
|
return value, nil
|
|
}
|
|
|
|
// Read bytes buffer and return int64
|
|
func Int64(buf *bytes.Buffer) (int64, error) {
|
|
var value int64
|
|
if err := readNumber(buf, &value, 8); err != nil {
|
|
return 0, err
|
|
}
|
|
|
|
return value, nil
|
|
}
|
|
|
|
// Read bytes buffer and return uint16
|
|
func Uint16(buf *bytes.Buffer) (uint16, error) {
|
|
var value uint16
|
|
if err := readNumber(buf, &value, 2); err != nil {
|
|
return 0, err
|
|
}
|
|
|
|
return value, nil
|
|
}
|
|
|
|
// Read bytes buffer and return uint32
|
|
func Uint32(buf *bytes.Buffer) (uint32, error) {
|
|
var value uint32
|
|
if err := readNumber(buf, &value, 4); err != nil {
|
|
return 0, err
|
|
}
|
|
|
|
return value, nil
|
|
}
|
|
|
|
// Read bytes buffer and return uint64
|
|
func Uint64(buf *bytes.Buffer) (uint64, error) {
|
|
var value uint64
|
|
if err := readNumber(buf, &value, 8); err != nil {
|
|
return 0, err
|
|
}
|
|
|
|
return value, nil
|
|
}
|
|
|
|
// Read bytes buffer and return float32
|
|
func Float32(buf *bytes.Buffer) (float32, error) {
|
|
var value float32
|
|
if err := readNumber(buf, &value, 4); err != nil {
|
|
return 0, err
|
|
}
|
|
|
|
return value, nil
|
|
}
|
|
|
|
// Read bytes buffer and return float64
|
|
func Float64(buf *bytes.Buffer) (float64, error) {
|
|
var value float64
|
|
if err := readNumber(buf, &value, 8); err != nil {
|
|
return 0, err
|
|
}
|
|
|
|
return value, nil
|
|
}
|
|
|
|
// Read bytes buffer to first 0x00 delimiter and return as string
|
|
func String(buf *bytes.Buffer) (string, error) {
|
|
value, err := buf.ReadBytes(0x00)
|
|
if err != nil {
|
|
return "", err
|
|
}
|
|
|
|
return string(value[:len(value)-1]), nil
|
|
}
|
|
|
|
// Read bytes buffer by size count and return as string
|
|
func StringLen(buf *bytes.Buffer, size int) (string, error) {
|
|
if err := checkLength(buf, size); err != nil {
|
|
return "", err
|
|
}
|
|
|
|
value := make([]byte, size)
|
|
n, err := buf.Read(value)
|
|
if err != nil {
|
|
return "", err
|
|
}
|
|
|
|
if n != size {
|
|
return "", fmt.Errorf("%w: got '%s' with %d length but expected %d", ErrString, value, n, size)
|
|
}
|
|
|
|
return string(value), nil
|
|
}
|
|
|
|
// Read bytes buffer as float32 and return as time.Duration
|
|
func Duration32(buf *bytes.Buffer) (time.Duration, error) {
|
|
f, err := Float32(buf)
|
|
if err != nil {
|
|
return 0, err
|
|
}
|
|
|
|
seconds := int64(f)
|
|
nanoseconds := int64(math.Round(float64(f-float32(seconds)) * 1e9))
|
|
|
|
return time.Duration(seconds)*time.Second + time.Duration(nanoseconds)*time.Nanosecond, nil
|
|
}
|
|
|
|
// Read bytes buffer as float64 and return as time.Duration
|
|
func Duration64(buf *bytes.Buffer) (time.Duration, error) {
|
|
f, err := Float64(buf)
|
|
if err != nil {
|
|
return 0, err
|
|
}
|
|
|
|
seconds := int64(f)
|
|
nanoseconds := int64(math.Round((f - float64(seconds)) * 1e9))
|
|
|
|
return time.Duration(seconds)*time.Second + time.Duration(nanoseconds)*time.Nanosecond, nil
|
|
}
|
|
|
|
// Read bytes buffer to first 0x00 delimiter
|
|
func BytesPage(buf *bytes.Buffer) ([]byte, error) {
|
|
value, err := buf.ReadBytes(0x00)
|
|
if err != nil {
|
|
return nil, err
|
|
}
|
|
n := len(value) - 1
|
|
|
|
return value[:n], nil
|
|
}
|
|
|
|
// Replace Escape sequence to Escape value
|
|
//
|
|
// {0x01, 0x01} -> 0x01
|
|
// {0x01, 0x02} -> 0x00
|
|
// {0x01, 0x03} -> 0xFF
|
|
func EscapeSequences(data []byte) []byte {
|
|
var buf bytes.Buffer
|
|
|
|
for i := 0; i < len(data); i++ {
|
|
if data[i] == 0x01 && i+1 < len(data) {
|
|
switch data[i+1] {
|
|
case 0x01:
|
|
buf.WriteByte(0x01)
|
|
i++
|
|
case 0x02:
|
|
buf.WriteByte(0x00)
|
|
i++
|
|
case 0x03:
|
|
buf.WriteByte(0xFF)
|
|
i++
|
|
default:
|
|
buf.WriteByte(data[i])
|
|
}
|
|
} else {
|
|
buf.WriteByte(data[i])
|
|
}
|
|
}
|
|
|
|
return buf.Bytes()
|
|
}
|