dsfx/internal/lib/frame/frame.go

92 lines
2.3 KiB
Go
Raw Permalink Normal View History

2025-03-09 15:52:33 -04:00
package frame
2025-03-08 15:07:27 -05:00
import (
"encoding/binary"
"errors"
"io"
)
const (
// MaxFrameSize is the maximum size of a frame. It is set to 65534 bytes,
// which is one byte less than the maximum value of a uint16 (65535).
MaxFrameSize uint16 = 65535
)
// Frame is a Frame that uses a length prefix to frame the data.
type Frame struct {
contents []byte
}
2025-03-09 17:09:21 -04:00
// New creates a new Frame with a length prefix.
func New(contents []byte) *Frame {
2025-03-08 15:07:27 -05:00
return &Frame{
contents: contents,
}
}
// Contents implements Frame.
func (l *Frame) Contents() []byte {
return l.contents
}
// Len implements Frame.
func (l *Frame) Len() uint16 {
return uint16(len(l.contents))
}
// ReadFrom implements Frame.
func (lpf *Frame) ReadFrom(r io.Reader) (int64, error) {
// LPF expects a 2-byte length prefix followed by the contents.
header := make([]byte, 2)
// Read the header (2 bytes) from the reader. io.ReadFull will return an
// error if it doesn't read exactly 2 bytes.
if _, err := io.ReadFull(r, header); err != nil {
return 0, err
}
// Calculate the length of the payload.
payloadLen := binary.BigEndian.Uint16(header)
// Check if the payload length exceeds the maximum frame size.
if payloadLen >= MaxFrameSize {
return 0, errors.New("payload length exceeds maximum frame size")
}
// Read the payload from the reader.
payload := make([]byte, payloadLen)
if _, err := io.ReadFull(r, payload); err != nil {
return 0, err
}
// Set the contents of the frame.
lpf.contents = payload
// Calculate the total length of the frame.
return int64(2 + len(payload)), nil
}
// WriteTo implements Frame.
func (l *Frame) WriteTo(w io.Writer) (int64, error) {
// Check if the payload length exceeds the maximum frame size.
if uint16(len(l.contents)) >= MaxFrameSize {
return 0, errors.New("payload length exceeds maximum frame size")
}
// Create a buffer to hold the length prefix and the payload.
lenBuf := make([]byte, 2)
binary.BigEndian.PutUint16(lenBuf, uint16(len(l.contents)))
// Write the header to the buffer.
if _, err := w.Write(lenBuf); err != nil {
return 0, errors.New("failed to write frame header")
}
// Write the payload to the buffer.
if _, err := w.Write(l.contents); err != nil {
return 0, errors.New("failed to write frame payload")
}
// Calculate the total length of the frame.
return int64(2 + len(l.contents)), nil
}