/* SeekableBuffer Copyright (c) 2023 aler9 Copyright (c) 2025 Zervó Zadachin Implementation based on code from "bluenviron/mediacommon". See: https://github.com/bluenviron/mediacommon/blob/main/pkg/formats/fmp4/seekablebuffer/seekablebuffer.go Original code was licensed under the MIT License. See: https://github.com/bluenviron/mediacommon/blob/main/LICENSE */ package seekablebuffer import ( "bytes" "fmt" "io" ) // Buffer is a bytes.Buffer with an additional Seek() method. type Buffer struct { bytes.Buffer pos int64 } // Write implements io.Writer. func (b *Buffer) Write(p []byte) (int, error) { var n int if b.pos < int64(b.Len()) { n = copy(b.Bytes()[b.pos:], p) p = p[n:] } if len(p) > 0 { // Buffer.Write should never return an error here. nn, _ := b.Buffer.Write(p) n += nn } b.pos += int64(n) return n, nil } // Read (almost) implements io.Reader. func (b *Buffer) Read(_ []byte) (int, error) { return 0, fmt.Errorf("read not implemented") } // Seek implements io.Seeker. func (b *Buffer) Seek(offset int64, whence int) (int64, error) { var pos2 int64 switch whence { case io.SeekStart: pos2 = offset case io.SeekCurrent: pos2 = b.pos + offset case io.SeekEnd: pos2 = int64(b.Len()) + offset default: return 0, fmt.Errorf("invalid seek whence") } if pos2 < 0 { return 0, fmt.Errorf("negative position") } b.pos = pos2 // Expand buffer if needed diff := b.pos - int64(b.Len()) if diff > 0 { // Buffer.Write should never return an error here. b.Buffer.Write(make([]byte, diff)) } return pos2, nil } // Reset resets the buffer state. func (b *Buffer) Reset() { b.Buffer.Reset() b.pos = 0 }