blob: f6ad06a3b5bf4e92c3280d086e929f7f5265d912 [file] [log] [blame]
package progressreader
import (
"io"
)
type StreamFormatter interface {
FormatProg(string, string, interface{}) []byte
FormatStatus(string, string, ...interface{}) []byte
FormatError(error) []byte
}
type PR_JSONProgress interface {
GetCurrent() int
GetTotal() int
}
type JSONProg struct {
Current int
Total int
}
func (j *JSONProg) GetCurrent() int {
return j.Current
}
func (j *JSONProg) GetTotal() int {
return j.Total
}
// Reader with progress bar
type Config struct {
In io.ReadCloser // Stream to read from
Out io.Writer // Where to send progress bar to
Formatter StreamFormatter
Size int
Current int
LastUpdate int
NewLines bool
ID string
Action string
}
func New(newReader Config) *Config {
return &newReader
}
func (config *Config) Read(p []byte) (n int, err error) {
read, err := config.In.Read(p)
config.Current += read
updateEvery := 1024 * 512 //512kB
if config.Size > 0 {
// Update progress for every 1% read if 1% < 512kB
if increment := int(0.01 * float64(config.Size)); increment < updateEvery {
updateEvery = increment
}
}
if config.Current-config.LastUpdate > updateEvery || err != nil {
config.Out.Write(config.Formatter.FormatProg(config.ID, config.Action, &JSONProg{Current: config.Current, Total: config.Size}))
config.LastUpdate = config.Current
}
// Send newline when complete
if config.NewLines && err != nil && read == 0 {
config.Out.Write(config.Formatter.FormatStatus("", ""))
}
return read, err
}
func (config *Config) Close() error {
config.Current = config.Size
config.Out.Write(config.Formatter.FormatProg(config.ID, config.Action, &JSONProg{Current: config.Current, Total: config.Size}))
return config.In.Close()
}