2022-10-09 20:27:14 +00:00
|
|
|
package nixwire
|
|
|
|
|
|
|
|
import (
|
|
|
|
"encoding/binary"
|
2022-10-09 22:48:18 +00:00
|
|
|
"fmt"
|
2022-10-09 20:27:14 +00:00
|
|
|
"io"
|
|
|
|
)
|
|
|
|
|
|
|
|
type Serializer struct {
|
|
|
|
io.Writer
|
|
|
|
}
|
|
|
|
|
|
|
|
func (w Serializer) WritePadding(n int64) (int64, error) {
|
|
|
|
if n%8 > 0 {
|
|
|
|
n, err := w.Write(make([]byte, 8-(n%8)))
|
|
|
|
return int64(n), err
|
|
|
|
}
|
|
|
|
return 0, nil
|
|
|
|
}
|
|
|
|
|
|
|
|
func (w Serializer) WriteUint64(n uint64) (int64, error) {
|
|
|
|
buf := make([]byte, 8)
|
|
|
|
binary.LittleEndian.PutUint64(buf, n)
|
|
|
|
wrote, err := w.Write(buf)
|
|
|
|
return int64(wrote), err
|
|
|
|
}
|
|
|
|
|
|
|
|
func (w Serializer) WriteString(s string) (int64, error) {
|
|
|
|
nSize, err := w.WriteUint64(uint64(len(s)))
|
|
|
|
if err != nil {
|
|
|
|
return int64(nSize), err
|
|
|
|
}
|
|
|
|
|
|
|
|
nData, err := w.Write([]byte(s))
|
|
|
|
if err != nil {
|
|
|
|
return int64(nSize) + int64(nData), err
|
|
|
|
}
|
|
|
|
|
|
|
|
nPad, err := w.WritePadding(int64(len(s)))
|
|
|
|
return int64(nSize) + int64(nData) + int64(nPad), err
|
|
|
|
}
|
2022-10-09 22:48:18 +00:00
|
|
|
|
|
|
|
type Deserializer struct {
|
|
|
|
io.Reader
|
|
|
|
}
|
|
|
|
|
|
|
|
func (r Deserializer) ReadPadding(n uint64) error {
|
|
|
|
if n%8 == 0 {
|
|
|
|
return nil
|
|
|
|
}
|
|
|
|
|
|
|
|
buf := make([]byte, 8-(int(n)%8))
|
|
|
|
if _, err := io.ReadFull(r, buf); err != nil {
|
|
|
|
return fmt.Errorf("reading padding: %w", err)
|
|
|
|
}
|
|
|
|
for _, n := range buf {
|
|
|
|
if n != 0 {
|
|
|
|
return fmt.Errorf("padding was not all 0")
|
|
|
|
}
|
|
|
|
}
|
|
|
|
return nil
|
|
|
|
}
|
|
|
|
|
|
|
|
func (r Deserializer) ReadUint64() (uint64, error) {
|
|
|
|
buf := make([]byte, 8)
|
|
|
|
if _, err := io.ReadFull(r, buf); err != nil {
|
|
|
|
return 0, fmt.Errorf("reading uint64: %w", err)
|
|
|
|
}
|
|
|
|
|
|
|
|
return binary.LittleEndian.Uint64(buf), nil
|
|
|
|
}
|
|
|
|
|
|
|
|
func (r Deserializer) ReadString() (string, error) {
|
|
|
|
strLen, err := r.ReadUint64()
|
|
|
|
if err != nil {
|
|
|
|
return "", fmt.Errorf("reading length: %w", err)
|
|
|
|
}
|
|
|
|
|
|
|
|
strBuf := make([]byte, int(strLen))
|
|
|
|
if _, err := io.ReadFull(r, strBuf); err != nil {
|
|
|
|
return "", fmt.Errorf("reading string buffer: %w", err)
|
|
|
|
}
|
|
|
|
|
|
|
|
if err := r.ReadPadding(strLen); err != nil {
|
|
|
|
return "", fmt.Errorf("reading string padding: %w", err)
|
|
|
|
}
|
|
|
|
|
|
|
|
return string(strBuf), nil
|
|
|
|
}
|
|
|
|
|
|
|
|
func (r Deserializer) ReadStrings() ([]string, error) {
|
|
|
|
setLen, err := r.ReadUint64()
|
|
|
|
if err != nil {
|
|
|
|
return nil, fmt.Errorf("reading string set length: %w", err)
|
|
|
|
}
|
|
|
|
|
|
|
|
xs := make([]string, int(setLen))
|
|
|
|
for n := uint64(0); n < setLen; n++ {
|
|
|
|
xs[n], err = r.ReadString()
|
|
|
|
if err != nil {
|
|
|
|
return nil, fmt.Errorf("reading string %d of %d: %w", n, setLen, err)
|
|
|
|
}
|
|
|
|
}
|
|
|
|
return xs, nil
|
|
|
|
}
|