func (seq Sequence) UpdateValueAtOffset(offset int, e expr.Expr, params expr.Params, metadata goexpr.Params) {
	offset = offset + Width64bits
	e.Update(seq[offset:], params, metadata)
}
UpdateValueAtOffset updates the value at the given byte offset by applying
the supplied Params to the given expression. metadata represents metadata
about the operation that's used by the Expr as well (e.g. information about
the dimensions associated to the value).
package encoding
import (
	"fmt"
	"math"
	"time"
	"github.com/getlantern/goexpr"
	"github.com/getlantern/golog"
	"github.com/getlantern/zenodb/expr"
)
var (
	log = golog.LoggerFor("zenodb.encoding")
)
type Sequence []byte
func NewSequence(width int, numPeriods int) Sequence {
	return make(Sequence, Width64bits+numPeriods*width)
}
func NewFloatValue(e expr.Expr, ts time.Time, val float64) Sequence {
	return NewValue(e, ts, expr.FloatParams(val), nil)
}
func NewValue(e expr.Expr, ts time.Time, params expr.Params, metadata goexpr.Params) Sequence {
	seq := NewSequence(e.EncodedWidth(), 1)
	seq.SetUntil(ts)
	seq.UpdateValueAt(0, e, params, metadata)
	return seq
}
func (seq Sequence) Until() time.Time {
	if len(seq) == 0 {
		return zeroTime
	}
	return TimeFromBytes(seq)
}
func (seq Sequence) UntilInt() int64 {
	if len(seq) == 0 {
		return 0
	}
	return TimeIntFromBytes(seq)
}
func (seq Sequence) AsOf(width int, resolution time.Duration) time.Time {
	if len(seq) == 0 {
		return zeroTime
	}
	return seq.Until().Add(-1 * time.Duration(seq.NumPeriods(width)) * resolution)
}
func (seq Sequence) SetUntil(t time.Time) {
	Binary.PutUint64(seq, uint64(t.UnixNano()))
}
func (seq Sequence) NumPeriods(width int) int {
	if len(seq) == 0 {
		return 0
	}
	return seq.DataLength() / width
}
func (seq Sequence) DataLength() int {
	return len(seq) - Width64bits
}
func (seq Sequence) ValueAtTime(t time.Time, e expr.Expr, resolution time.Duration) (val float64, found bool) {
	if e.IsConstant() {
		val, found, _ = e.Get(nil)
		return
	}
	if len(seq) == 0 {
		return 0, false
	}
	until := seq.Until()
	t = RoundTimeUntilUp(t, resolution, until)
	if t.After(until) {
		return 0, false
	}
	period := int(until.Sub(t) / resolution)
	return seq.ValueAt(period, e)
}
func (seq Sequence) ValueAt(period int, e expr.Expr) (val float64, found bool) {
	if e.IsConstant() {
		val, found, _ = e.Get(nil)
		return
	}
	if len(seq) == 0 {
		return 0, false
	}
	if period < 0 {
		return 0, false
	}
	return seq.ValueAtOffset(period*e.EncodedWidth(), e)
}
func (seq Sequence) ValueAtOffset(offset int, e expr.Expr) (val float64, found bool) {
	if e.IsConstant() {
		val, found, _ = e.Get(nil)
		return
	}
	if len(seq) == 0 {
		return 0, false
	}
	offset = offset + Width64bits
	if offset >= len(seq) {
		return 0, false
	}
	val, wasSet, _ := e.Get(seq[offset:])
	return val, wasSet
}
func (seq Sequence) UpdateValueAt(period int, e expr.Expr, params expr.Params, metadata goexpr.Params) {
	seq.UpdateValueAtOffset(period*e.EncodedWidth(), e, params, metadata)
}