diff options
Diffstat (limited to 'protocol/sideband64k/decoder.go')
| -rw-r--r-- | protocol/sideband64k/decoder.go | 158 |
1 files changed, 0 insertions, 158 deletions
diff --git a/protocol/sideband64k/decoder.go b/protocol/sideband64k/decoder.go deleted file mode 100644 index 57541567..00000000 --- a/protocol/sideband64k/decoder.go +++ /dev/null @@ -1,158 +0,0 @@ -package sideband64k - -import ( - "fmt" - "io" - - "codeberg.org/lindenii/furgit/protocol/pktline" -) - -// ReadOptions controls sideband decoding behavior. -type ReadOptions struct { - // ChompLF removes one trailing '\n' from FrameData payloads only. - ChompLF bool -} - -// Decoder reads side-band-64k frames from an io.Reader. -// -// It preserves frame boundaries and supports one-frame lookahead via -// PeekFrame. -type Decoder struct { - dec *pktline.Decoder - maxData int - opts ReadOptions - - peeked bool - peek Frame - peekErr error -} - -// NewDecoder creates a decoder over r. -func NewDecoder(r io.Reader, opts ReadOptions) *Decoder { - d := &Decoder{ - dec: pktline.NewDecoder(r, pktline.ReadOptions{}), - maxData: DataMax, - opts: opts, - } - d.dec.SetMaxData(pktline.LargePacketDataMax) - - return d -} - -// SetMaxData sets maximum payload size accepted for one sideband data packet. -// -// Non-positive n resets to DataMax. -func (d *Decoder) SetMaxData(n int) { - if n <= 0 { - d.maxData = DataMax - - return - } - - d.maxData = n -} - -// ReadFrame reads one frame. -func (d *Decoder) ReadFrame() (Frame, error) { - if d.peeked { - d.peeked = false - - return cloneFrame(d.peek), d.peekErr - } - - return d.readFrame() -} - -// PeekFrame returns the next frame without consuming it. -func (d *Decoder) PeekFrame() (Frame, error) { - if !d.peeked { - d.peek, d.peekErr = d.readFrame() - d.peeked = true - } - - return cloneFrame(d.peek), d.peekErr -} - -func (d *Decoder) readFrame() (Frame, error) { - f, err := d.dec.ReadFrame() - if err != nil { - return Frame{}, err - } - - switch f.Type { - case pktline.PacketFlush: - return Frame{Type: FrameFlush}, nil - case pktline.PacketDelim: - return Frame{Type: FrameDelim}, nil - case pktline.PacketResponseEnd: - return Frame{Type: FrameResponseEnd}, nil - case pktline.PacketData: - if len(f.Payload) == 0 { - return Frame{}, &ProtocolError{Reason: "missing sideband designator"} - } - - payload := f.Payload[1:] - if len(payload) > d.effectiveMaxData() { - return Frame{}, fmt.Errorf("%w: %d > %d", ErrTooLarge, len(payload), d.effectiveMaxData()) - } - - band := Band(f.Payload[0]) - if !validBand(band) { - return Frame{}, &ProtocolError{Reason: fmt.Sprintf("%v: %d", ErrInvalidBand, band)} - } - - payload = append([]byte(nil), payload...) - if d.opts.ChompLF && band == BandData && len(payload) > 0 && payload[len(payload)-1] == '\n' { - payload = payload[:len(payload)-1] - } - - return Frame{ - Type: frameTypeForBand(band), - Payload: payload, - }, nil - default: - return Frame{}, &ProtocolError{Reason: "unknown pkt-line frame type"} - } -} - -func (d *Decoder) effectiveMaxData() int { - return effectiveMaxData(d.maxData) -} - -func cloneFrame(f Frame) Frame { - if f.Type == FrameFlush || f.Type == FrameDelim || f.Type == FrameResponseEnd { - return Frame{Type: f.Type} - } - - out := Frame{Type: f.Type} - if f.Payload != nil { - out.Payload = append([]byte(nil), f.Payload...) - } - - return out -} - -func validBand(band Band) bool { - return band == BandData || band == BandProgress || band == BandError -} - -func frameTypeForBand(band Band) FrameType { - switch band { - case BandData: - return FrameData - case BandProgress: - return FrameProgress - case BandError: - return FrameError - default: - panic("invalid sideband64k band") - } -} - -func effectiveMaxData(n int) int { - if n <= 0 || n > DataMax { - return DataMax - } - - return n -} |
