// 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 ( "bytes" "io" "log" "time" ) type decoder struct { r *reader } // Decode decodes an encoded string using the unicode collation algorithm. func decode(data []byte, items ...interface{}) { newDecoder(bytes.NewReader(data)).Decode(items...) } func newDecoder(r io.Reader) *decoder { return &decoder{ r: newReader(r), } } func (d *decoder) Decode(items ...interface{}) { for _, item := range items { switch value := item.(type) { case *time.Time: *value = d.r.FindTime() case *bool: *value = d.r.FindBool() case *[]byte: *value = d.r.FindBytes() case *string: *value = d.r.FindString() case *int: *value = d.r.FindNumberInt() case *int8: *value = d.r.FindNumberInt8() case *int16: *value = d.r.FindNumberInt16() case *int32: *value = d.r.FindNumberInt32() case *int64: *value = d.r.FindNumberInt64() case *uint: *value = d.r.FindNumberUint() case *uint8: *value = d.r.FindNumberUint8() case *uint16: *value = d.r.FindNumberUint16() case *uint32: *value = d.r.FindNumberUint32() case *uint64: *value = d.r.FindNumberUint64() case *float32: *value = d.r.FindNumberFloat32() case *float64: *value = d.r.FindNumberFloat64() case *[]bool: if d.r.ReadNext(cARRAY) { for !d.r.ReadNext(cTERM) { *value = append(*value, d.r.FindBool()) } } case *[]string: if d.r.ReadNext(cARRAY) { for !d.r.ReadNext(cTERM) { *value = append(*value, d.r.FindString()) } } case *[]int: if d.r.ReadNext(cARRAY) { for !d.r.ReadNext(cTERM) { *value = append(*value, d.r.FindNumberInt()) } } case *[]int8: if d.r.ReadNext(cARRAY) { for !d.r.ReadNext(cTERM) { *value = append(*value, d.r.FindNumberInt8()) } } case *[]int16: if d.r.ReadNext(cARRAY) { for !d.r.ReadNext(cTERM) { *value = append(*value, d.r.FindNumberInt16()) } } case *[]int32: if d.r.ReadNext(cARRAY) { for !d.r.ReadNext(cTERM) { *value = append(*value, d.r.FindNumberInt32()) } } case *[]int64: if d.r.ReadNext(cARRAY) { for !d.r.ReadNext(cTERM) { *value = append(*value, d.r.FindNumberInt64()) } } case *[]uint: if d.r.ReadNext(cARRAY) { for !d.r.ReadNext(cTERM) { *value = append(*value, d.r.FindNumberUint()) } } case *[]uint16: if d.r.ReadNext(cARRAY) { for !d.r.ReadNext(cTERM) { *value = append(*value, d.r.FindNumberUint16()) } } case *[]uint32: if d.r.ReadNext(cARRAY) { for !d.r.ReadNext(cTERM) { *value = append(*value, d.r.FindNumberUint32()) } } case *[]uint64: if d.r.ReadNext(cARRAY) { for !d.r.ReadNext(cTERM) { *value = append(*value, d.r.FindNumberUint64()) } } case *[]float32: if d.r.ReadNext(cARRAY) { for !d.r.ReadNext(cTERM) { *value = append(*value, d.r.FindNumberFloat32()) } } case *[]float64: if d.r.ReadNext(cARRAY) { for !d.r.ReadNext(cTERM) { *value = append(*value, d.r.FindNumberFloat64()) } } case *[]interface{}: if d.r.ReadNext(cARRAY) { for !d.r.ReadNext(cTERM) { switch fnd := d.r.FindNext(); fnd { default: log.Panicf("No item found in *[]interface{} - but found %#v %#q", fnd, fnd) case cNILL: *value = append(*value, d.r.FindNull()) case cBOOL: *value = append(*value, d.r.FindBool()) case cTIME: *value = append(*value, d.r.FindTime()) case cNUMBER: *value = append(*value, d.r.FindNumber()) case cSTRING, cPREFIX, cSUFFIX: *value = append(*value, d.r.FindString()) } } d.r.ReadNext(cTERM) } case *interface{}: switch fnd := d.r.FindNext(); fnd { default: log.Panicf("No item found in *interface{} - but found %#v %#q", fnd, fnd) case cNILL: *value = d.r.FindNull() case cBOOL: *value = d.r.FindBool() case cTIME: *value = d.r.FindTime() case cNUMBER: *value = d.r.FindNumber() case cSTRING, cPREFIX, cSUFFIX: *value = d.r.FindString() case cARRAY: if d.r.ReadNext(cARRAY) { *value = []interface{}{} for !d.r.ReadNext(cTERM) { switch d.r.FindNext() { default: log.Panicf("No item found in *interface{}...[]interface{} - but found %#v %#q", fnd, fnd) case cNILL: *value = append((*value).([]interface{}), []interface{}{d.r.FindNull()}...) case cBOOL: *value = append((*value).([]interface{}), []interface{}{d.r.FindBool()}...) case cTIME: *value = append((*value).([]interface{}), []interface{}{d.r.FindTime()}...) case cNUMBER: *value = append((*value).([]interface{}), []interface{}{d.r.FindNumber()}...) case cSTRING, cPREFIX, cSUFFIX: *value = append((*value).([]interface{}), []interface{}{d.r.FindString()}...) } } d.r.ReadNext(cTERM) } } } } }