// Copyright © 2016 Abcum Ltd // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. package keys import ( "encoding/binary" "math" "time" "github.com/abcum/bump" ) type reader struct { r *bump.Reader } func newReader() *reader { return &reader{ r: bump.NewReader(nil), } } func (r *reader) unread() { } func (r *reader) lookNext() (byt byte) { byt, _ = r.r.PeekByte() return } func (r *reader) readNext(exp byte) (fnd bool) { if byt, _ := r.r.PeekByte(); byt == exp { r.r.ReadByte() return true } return false } func (r *reader) readSize(sze int) (byt []byte) { byt, _ = r.r.ReadBytes(sze) return byt } func (r *reader) readUpto(exp ...byte) (byt []byte) { LOOP: for { bit, _ := r.r.ReadByte() byt = append(byt, bit) if bit != exp[0] { continue } for j := 1; j < len(exp); j++ { if r.readNext(exp[j]) { byt = append(byt, bit) continue } break LOOP } break } return byt[:len(byt)-len(exp)] } // -------------------------------------------------- // -------------------------------------------------- // -------------------------------------------------- // -------------------------------------------------- // -------------------------------------------------- func (r *reader) readAny() (val interface{}) { return r.readUpto(bEND) } func (r *reader) readNull() (val interface{}) { if r.readNext(bNIL) { r.readNext(bEND) } return } func (r *reader) readTime() (val time.Time) { if r.readNext(bTME) { bin := r.readSize(8) dec := binary.BigEndian.Uint64(bin) val = time.Unix(0, int64(dec)).UTC() r.readNext(bEND) } return } func (r *reader) readBool() (val bool) { if r.readNext(bVAL) { val = r.readNext(bVAL) r.readNext(bEND) } return } func (r *reader) readBytes() (val []byte) { if r.readNext(bSTR) { val = r.readUpto(bEND, bEND) } return } func (r *reader) readFloat() (val float64) { if r.readNext(bNEG) { bin := r.readSize(8) dec := binary.BigEndian.Uint64(bin) val = math.Float64frombits(^dec) r.readNext(bEND) } else if r.readNext(bPOS) { bin := r.readSize(8) dec := binary.BigEndian.Uint64(bin) val = math.Float64frombits(dec) r.readNext(bEND) } return } func (r *reader) readString() (val string) { if r.readNext(bSTR) { val = string(r.readUpto(bEND, bEND)) } else if r.readNext(bPRE) { val = Prefix r.readNext(bEND) } else if r.readNext(bSUF) { val = Suffix r.readNext(bEND) } return } func (r *reader) readNumber() (val interface{}) { var num float64 if r.readNext(bNEG) { bin := r.readSize(8) dec := binary.BigEndian.Uint64(bin) num = math.Float64frombits(^dec) r.readNext(bEND) } else if r.readNext(bPOS) { bin := r.readSize(8) dec := binary.BigEndian.Uint64(bin) num = math.Float64frombits(dec) r.readNext(bEND) } if math.Trunc(num) == num { return int64(math.Trunc(num)) } return num } func (r *reader) readArray() (val []interface{}) { if r.readNext(bARR) { for !r.readNext(bEND) { switch r.lookNext() { default: val = append(val, []interface{}{r.readAny()}...) case bNIL: val = append(val, []interface{}{r.readNull()}...) case bVAL: val = append(val, []interface{}{r.readBool()}...) case bTME: val = append(val, []interface{}{r.readTime()}...) case bNEG, bPOS: val = append(val, []interface{}{r.readNumber()}...) case bSTR, bPRE, bSUF: val = append(val, []interface{}{r.readString()}...) case bARR: val = append(val, []interface{}{r.readArray()}...) } } r.readNext(bEND) } return }