
Add a specialised bytes.Buffer variant with seeking capabilities. This allows writers without seeking support to serialize using NodeSerializerStreamed.
90 lines
1.6 KiB
Go
90 lines
1.6 KiB
Go
/*
|
|
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
|
|
}
|