58 lines
1.3 KiB
Go
58 lines
1.3 KiB
Go
package streams
|
|
|
|
import (
|
|
"io"
|
|
)
|
|
|
|
type MetadataInjector struct {
|
|
io.Reader
|
|
MetadataInterval int
|
|
blockOffset int
|
|
Metadata map[string]string
|
|
metadataBuf []byte
|
|
}
|
|
|
|
func NewMetadataInjector(r io.Reader, metadataInterval int) *MetadataInjector {
|
|
return &MetadataInjector{
|
|
Reader: r,
|
|
MetadataInterval: metadataInterval,
|
|
}
|
|
}
|
|
|
|
func (mi *MetadataInjector) Read(data []byte) (n int, err error) {
|
|
if mi.metadataBuf != nil && len(mi.metadataBuf) > 0 {
|
|
bytesToRead := len(data)
|
|
if bytesToRead < len(mi.metadataBuf) {
|
|
// only read as much as possible
|
|
copy(data, mi.metadataBuf[0:bytesToRead])
|
|
n = bytesToRead
|
|
mi.metadataBuf = mi.metadataBuf[bytesToRead:]
|
|
return
|
|
}
|
|
// read everything
|
|
copy(data, mi.metadataBuf)
|
|
n = len(mi.metadataBuf)
|
|
mi.metadataBuf = nil
|
|
return
|
|
}
|
|
|
|
bytesToRead := mi.MetadataInterval - mi.blockOffset
|
|
if bytesToRead > len(data) {
|
|
bytesToRead = len(data)
|
|
}
|
|
if bytesToRead > 0 {
|
|
n, err = mi.Reader.Read(data[0:bytesToRead])
|
|
if err != nil {
|
|
return
|
|
}
|
|
mi.blockOffset += n
|
|
}
|
|
if mi.blockOffset == mi.MetadataInterval {
|
|
mi.generateMetadataBuf() // will be read in on next Read call
|
|
mi.blockOffset = 0
|
|
} else if mi.blockOffset > mi.MetadataInterval {
|
|
panic("block offset higher than metadata interval, logical error")
|
|
}
|
|
return
|
|
}
|