package enc import ( "math" "gordenko.dev/dima/diploma/bin" ) type ReverseCumulativeDeltaDecompressor struct { buf []byte pos int bound int firstValue float64 lastValue float64 length uint16 coef float64 idxOf8 uint s8 byte } func NewReverseCumulativeDeltaDecompressor(buf []byte, fracDigits byte) *ReverseCumulativeDeltaDecompressor { var coef float64 = 1 if fracDigits > 0 { coef = math.Pow(10, float64(fracDigits)) } return &ReverseCumulativeDeltaDecompressor{ buf: buf, coef: coef, pos: len(buf), } } func (s *ReverseCumulativeDeltaDecompressor) NextValue() (value float64, done bool) { if s.length > 0 { s.length-- return s.lastValue, false } if s.pos < s.bound { return 0, true } if s.pos == len(s.buf) { u64, n, err := bin.GetVarUint64(s.buf) if err != nil { panic(err) } s.firstValue = float64(u64) / s.coef s.bound = n s.pos-- s.idxOf8 = uint(8 - s.buf[s.pos]) s.pos-- s.s8 = s.buf[s.pos] s.pos-- s.readVar() if s.length > 0 { s.length-- } return s.lastValue, false } if s.idxOf8 == 0 { s.s8 = s.buf[s.pos] s.pos-- } s.readVar() if s.length > 0 { s.length-- } return s.lastValue, false } func (s *ReverseCumulativeDeltaDecompressor) readVar() { u64, n, err := bin.ReverseGetVarUint64(s.buf[:s.pos+1]) if err != nil { panic(err) } s.pos -= n s.lastValue = s.firstValue + float64(u64)/s.coef var flag byte = 1 << s.idxOf8 if (s.s8 & flag) == flag { s.decodeLength() } if s.idxOf8 == 7 { s.idxOf8 = 0 } else { s.idxOf8++ } } func (s *ReverseCumulativeDeltaDecompressor) decodeLength() { b1 := s.buf[s.pos] s.pos-- if b1 < 128 { s.length = uint16(b1) } else { b2 := s.buf[s.pos] s.pos-- s.length = uint16(b1&127) | (uint16(b2) << 7) } s.length += 2 }