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 }