aboutsummaryrefslogtreecommitdiff
path: root/network/protocol/sideband64k/encoder.go
diff options
context:
space:
mode:
Diffstat (limited to 'network/protocol/sideband64k/encoder.go')
-rw-r--r--network/protocol/sideband64k/encoder.go98
1 files changed, 98 insertions, 0 deletions
diff --git a/network/protocol/sideband64k/encoder.go b/network/protocol/sideband64k/encoder.go
new file mode 100644
index 00000000..9f729d15
--- /dev/null
+++ b/network/protocol/sideband64k/encoder.go
@@ -0,0 +1,98 @@
+package sideband64k
+
+import (
+ "fmt"
+
+ "codeberg.org/lindenii/furgit/network/protocol/pktline"
+)
+
+// Encoder writes side-band-64k frames to a flush-capable output transport.
+//
+// It writes exactly one frame per method call and does not auto-chunk data.
+type Encoder struct {
+ enc *pktline.Encoder
+ maxData int
+}
+
+// NewEncoder creates an encoder over w.
+func NewEncoder(w pktline.WriteFlusher) *Encoder {
+ return &Encoder{
+ enc: pktline.NewEncoder(w),
+ maxData: DataMax,
+ }
+}
+
+// SetMaxData sets the maximum payload size accepted by WriteBand.
+//
+// Non-positive n resets to DataMax.
+func (e *Encoder) SetMaxData(n int) {
+ if n <= 0 {
+ e.maxData = DataMax
+
+ return
+ }
+
+ e.maxData = n
+}
+
+// WriteBand writes one side-band-64k data frame for the given band.
+func (e *Encoder) WriteBand(band Band, p []byte) error {
+ if !validBand(band) {
+ return fmt.Errorf("%w: %d", ErrInvalidBand, band)
+ }
+
+ maxData := e.effectiveMaxData()
+ if len(p) > maxData {
+ return fmt.Errorf("%w: %d > %d", ErrTooLarge, len(p), maxData)
+ }
+
+ framed := make([]byte, len(p)+1)
+ framed[0] = byte(band)
+ copy(framed[1:], p)
+
+ return e.enc.WriteData(framed)
+}
+
+// WriteData writes one band-1 data frame.
+func (e *Encoder) WriteData(p []byte) error {
+ return e.WriteBand(BandData, p)
+}
+
+// WriteProgress writes one band-2 progress frame.
+func (e *Encoder) WriteProgress(p []byte) error {
+ return e.WriteBand(BandProgress, p)
+}
+
+// WriteError writes one band-3 error frame.
+func (e *Encoder) WriteError(p []byte) error {
+ return e.WriteBand(BandError, p)
+}
+
+// WriteFlush writes control frame 0000 (flush-pkt).
+func (e *Encoder) WriteFlush() error {
+ return e.enc.WriteFlush()
+}
+
+// WriteDelim writes control frame 0001 (delim-pkt).
+func (e *Encoder) WriteDelim() error {
+ return e.enc.WriteDelim()
+}
+
+// WriteResponseEnd writes control frame 0002 (response-end-pkt).
+func (e *Encoder) WriteResponseEnd() error {
+ return e.enc.WriteResponseEnd()
+}
+
+// FlushIO flushes buffered output in the underlying transport.
+func (e *Encoder) FlushIO() error {
+ return e.enc.FlushIO()
+}
+
+// WriteFlushAndFlushIO writes a flush-pkt (0000) then flushes transport I/O.
+func (e *Encoder) WriteFlushAndFlushIO() error {
+ return e.enc.WriteFlushAndFlushIO()
+}
+
+func (e *Encoder) effectiveMaxData() int {
+ return effectiveMaxData(e.maxData)
+}