diff --git a/util/keys/keys_test.go b/util/keys/keys_test.go index d547e14f..77075935 100644 --- a/util/keys/keys_test.go +++ b/util/keys/keys_test.go @@ -220,10 +220,10 @@ func TestMain(t *testing.T) { IB: true, IF: false, IT: clock, - II: float64(19387), + II: float64(19387.1), ID: float64(183784.13413), - INA: []interface{}{true, false, nil, "Test", clock, float64(192), 1.1, 1.2, 1.3}, - AIN: []interface{}{true, false, nil, "Test", clock, float64(192), float64(MaxNumber), 1.1, 1.2, 1.3, []interface{}{"Test"}}, + INA: []interface{}{true, false, nil, "Test", clock, int64(192), 1.1, 1.2, 1.3}, + AIN: []interface{}{true, false, nil, "Test", clock, int64(192), 1.1, 1.2, 1.3, []interface{}{"Test"}}, }, }, } @@ -236,12 +236,12 @@ func TestMain(t *testing.T) { &Thing{KV: "kv", NS: "ns", DB: "db", TB: "person", ID: nil}, &Thing{KV: "kv", NS: "ns", DB: "db", TB: "person", ID: false}, &Thing{KV: "kv", NS: "ns", DB: "db", TB: "person", ID: true}, - // &Thing{KV: "kv", NS: "ns", DB: "db", TB: "person", ID: -9223372036854775807}, - // &Thing{KV: "kv", NS: "ns", DB: "db", TB: "person", ID: -2147483647}, - // &Thing{KV: "kv", NS: "ns", DB: "db", TB: "person", ID: -32767}, - // &Thing{KV: "kv", NS: "ns", DB: "db", TB: "person", ID: -12}, - // &Thing{KV: "kv", NS: "ns", DB: "db", TB: "person", ID: -2}, - // &Thing{KV: "kv", NS: "ns", DB: "db", TB: "person", ID: -1}, + &Thing{KV: "kv", NS: "ns", DB: "db", TB: "person", ID: -9223372036854775807}, + &Thing{KV: "kv", NS: "ns", DB: "db", TB: "person", ID: -2147483647}, + &Thing{KV: "kv", NS: "ns", DB: "db", TB: "person", ID: -32767}, + &Thing{KV: "kv", NS: "ns", DB: "db", TB: "person", ID: -12}, + &Thing{KV: "kv", NS: "ns", DB: "db", TB: "person", ID: -2}, + &Thing{KV: "kv", NS: "ns", DB: "db", TB: "person", ID: -1}, &Thing{KV: "kv", NS: "ns", DB: "db", TB: "person", ID: 0}, &Thing{KV: "kv", NS: "ns", DB: "db", TB: "person", ID: 1}, &Thing{KV: "kv", NS: "ns", DB: "db", TB: "person", ID: 2}, diff --git a/util/keys/reader.go b/util/keys/reader.go index b71f20c5..856b2174 100644 --- a/util/keys/reader.go +++ b/util/keys/reader.go @@ -18,6 +18,7 @@ import ( "bufio" "encoding/binary" "io" + "math" "time" ) @@ -122,66 +123,84 @@ func (r *reader) FindString() (val string) { return } -func (r *reader) FindNumber() (val float64) { - if r.ReadNext(cNUMBER) { - if r.ReadNext(cNILL) { - binary.Read(r.Reader, binary.BigEndian, &val) - val = 0 - val - r.ReadNext(cTERM) - } else if r.ReadNext(cBOOL) { - binary.Read(r.Reader, binary.BigEndian, &val) - r.ReadNext(cTERM) - } +func (r *reader) FindNumber() (val interface{}) { + var dec uint64 + var num float64 + if r.ReadNext(cNEG) { + binary.Read(r.Reader, binary.BigEndian, &dec) + num = math.Float64frombits(^dec) + r.ReadNext(cEND) + } else if r.ReadNext(cPOS) { + binary.Read(r.Reader, binary.BigEndian, &dec) + num = math.Float64frombits(dec) + r.ReadNext(cEND) + } + if math.Trunc(num) == num { + return int64(math.Trunc(num)) + } + return num +} + +func (r *reader) FindDouble() (val float64) { + var dec uint64 + if r.ReadNext(cNEG) { + binary.Read(r.Reader, binary.BigEndian, &dec) + val = math.Float64frombits(^dec) + r.ReadNext(cEND) + } else if r.ReadNext(cPOS) { + binary.Read(r.Reader, binary.BigEndian, &dec) + val = math.Float64frombits(dec) + r.ReadNext(cEND) } return } func (r *reader) FindNumberInt() (val int) { - return int(r.FindNumber()) + return int(r.FindDouble()) } func (r *reader) FindNumberInt8() (val int8) { - return int8(r.FindNumber()) + return int8(r.FindDouble()) } func (r *reader) FindNumberInt16() (val int16) { - return int16(r.FindNumber()) + return int16(r.FindDouble()) } func (r *reader) FindNumberInt32() (val int32) { - return int32(r.FindNumber()) + return int32(r.FindDouble()) } func (r *reader) FindNumberInt64() (val int64) { - return int64(r.FindNumber()) + return int64(r.FindDouble()) } func (r *reader) FindNumberUint() (val uint) { - return uint(r.FindNumber()) + return uint(r.FindDouble()) } func (r *reader) FindNumberUint8() (val uint8) { - return uint8(r.FindNumber()) + return uint8(r.FindDouble()) } func (r *reader) FindNumberUint16() (val uint16) { - return uint16(r.FindNumber()) + return uint16(r.FindDouble()) } func (r *reader) FindNumberUint32() (val uint32) { - return uint32(r.FindNumber()) + return uint32(r.FindDouble()) } func (r *reader) FindNumberUint64() (val uint64) { - return uint64(r.FindNumber()) + return uint64(r.FindDouble()) } func (r *reader) FindNumberFloat32() (val float32) { - return float32(r.FindNumber()) + return float32(r.FindDouble()) } func (r *reader) FindNumberFloat64() (val float64) { - return float64(r.FindNumber()) + return float64(r.FindDouble()) } func (r *reader) FindArray() (val []interface{}) { diff --git a/util/keys/writer.go b/util/keys/writer.go index 76aa7175..05512ad8 100644 --- a/util/keys/writer.go +++ b/util/keys/writer.go @@ -17,7 +17,10 @@ package keys import ( "encoding/binary" "io" + "math" + "reflect" "time" + "unsafe" ) type writer struct { @@ -38,94 +41,61 @@ func (w *writer) Write(i interface{}) { w.Writer.Write(v) case string: - w.Writer.Write([]byte(v)) + w.writeString(v) case time.Time: - binary.Write(w.Writer, binary.BigEndian, v.UnixNano()) + w.writeTime(v) case uint: - w.Write(bBOOL) - binary.Write(w.Writer, binary.BigEndian, float64(v)) - + w.writeNumber(float64(v)) case uint8: - w.Write(bBOOL) - binary.Write(w.Writer, binary.BigEndian, float64(v)) - + w.writeNumber(float64(v)) case uint16: - w.Write(bBOOL) - binary.Write(w.Writer, binary.BigEndian, float64(v)) - + w.writeNumber(float64(v)) case uint32: - w.Write(bBOOL) - binary.Write(w.Writer, binary.BigEndian, float64(v)) - + w.writeNumber(float64(v)) case uint64: - w.Write(bBOOL) - binary.Write(w.Writer, binary.BigEndian, float64(v)) + w.writeNumber(float64(v)) case int: - if v < 0 { - w.Write(bNILL) - binary.Write(w.Writer, binary.BigEndian, 0-float64(v)) - } else { - w.Write(bBOOL) - binary.Write(w.Writer, binary.BigEndian, float64(v)) - } - + w.writeNumber(float64(v)) case int8: - if v < 0 { - w.Write(bNILL) - binary.Write(w.Writer, binary.BigEndian, 0-float64(v)) - } else { - w.Write(bBOOL) - binary.Write(w.Writer, binary.BigEndian, float64(v)) - } - + w.writeNumber(float64(v)) case int16: - if v < 0 { - w.Write(bNILL) - binary.Write(w.Writer, binary.BigEndian, 0-float64(v)) - } else { - w.Write(bBOOL) - binary.Write(w.Writer, binary.BigEndian, float64(v)) - } - + w.writeNumber(float64(v)) case int32: - if v < 0 { - w.Write(bNILL) - binary.Write(w.Writer, binary.BigEndian, 0-float64(v)) - } else { - w.Write(bBOOL) - binary.Write(w.Writer, binary.BigEndian, float64(v)) - } - + w.writeNumber(float64(v)) case int64: - if v < 0 { - w.Write(bNILL) - binary.Write(w.Writer, binary.BigEndian, 0-float64(v)) - } else { - w.Write(bBOOL) - binary.Write(w.Writer, binary.BigEndian, float64(v)) - } + w.writeNumber(float64(v)) case float32: - if v < 0 { - w.Write(bNILL) - binary.Write(w.Writer, binary.BigEndian, 0-float64(v)) - } else { - w.Write(bBOOL) - binary.Write(w.Writer, binary.BigEndian, float64(v)) - } - + w.writeNumber(float64(v)) case float64: - if v < 0 { - w.Write(bNILL) - binary.Write(w.Writer, binary.BigEndian, 0-float64(v)) - } else { - w.Write(bBOOL) - binary.Write(w.Writer, binary.BigEndian, float64(v)) - } + w.writeNumber(float64(v)) } } + +func (w *writer) writeString(v string) { + b := *(*[]byte)(unsafe.Pointer((*reflect.SliceHeader)(unsafe.Pointer(&v)))) + w.Write(b) +} + +func (w *writer) writeTime(v time.Time) { + b := make([]byte, 8) + binary.BigEndian.PutUint64(b, uint64(v.UTC().UnixNano())) + w.Write(b) +} + +func (w *writer) writeNumber(v float64) { + b := make([]byte, 8) + if v < 0 { + w.Write(bNEG) + binary.BigEndian.PutUint64(b, ^math.Float64bits(v)) + } else { + w.Write(bPOS) + binary.BigEndian.PutUint64(b, math.Float64bits(v)) + } + w.Write(b) +}