276
vendor/github.com/russolsen/transit/value_decoder.go
generated
vendored
Normal file
276
vendor/github.com/russolsen/transit/value_decoder.go
generated
vendored
Normal file
@@ -0,0 +1,276 @@
|
||||
// Copyright 2016 Russ Olsen. All Rights Reserved.
|
||||
//
|
||||
// This code is a Go port of the Java version created and maintained by Cognitect, therefore:
|
||||
//
|
||||
// Copyright 2014 Cognitect. All Rights Reserved.
|
||||
//
|
||||
// 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 transit
|
||||
|
||||
import (
|
||||
"container/list"
|
||||
"encoding/base64"
|
||||
"github.com/pborman/uuid"
|
||||
"github.com/shopspring/decimal"
|
||||
"math"
|
||||
"math/big"
|
||||
"strconv"
|
||||
"time"
|
||||
)
|
||||
|
||||
// DecodeKeyword decodes ~: style keywords.
|
||||
func DecodeKeyword(d Decoder, x interface{}) (interface{}, error) {
|
||||
s := x.(string)
|
||||
var result = Keyword(s)
|
||||
return result, nil
|
||||
}
|
||||
|
||||
// DecodeKeyword decodes ~$ style symbols.
|
||||
func DecodeSymbol(d Decoder, x interface{}) (interface{}, error) {
|
||||
s := x.(string)
|
||||
var result = Symbol(s)
|
||||
return result, nil
|
||||
}
|
||||
|
||||
// DecodeIdentity returns the value unchanged.
|
||||
func DecodeIdentity(d Decoder, x interface{}) (interface{}, error) {
|
||||
return x, nil
|
||||
}
|
||||
|
||||
// DecodeCMap decodes maps with composite keys.
|
||||
func DecodeCMap(d Decoder, x interface{}) (interface{}, error) {
|
||||
|
||||
tagged := x.(TaggedValue)
|
||||
|
||||
if !IsGenericArray(tagged.Value) {
|
||||
return nil, NewTransitError("Cmap contents are not an array.", tagged)
|
||||
}
|
||||
|
||||
array := tagged.Value.([]interface{})
|
||||
|
||||
if (len(array) % 2) != 0 {
|
||||
return nil, NewTransitError("Cmap contents must contain an even number of elements.", tagged)
|
||||
}
|
||||
|
||||
var result = NewCMap()
|
||||
|
||||
l := len(array)
|
||||
|
||||
for i := 0; i < l; i += 2 {
|
||||
key := array[i]
|
||||
value := array[i+1]
|
||||
result.Append(key, value)
|
||||
}
|
||||
|
||||
return result, nil
|
||||
}
|
||||
|
||||
// DecodeSet decodes a transit set into a transit.Set instance.
|
||||
func DecodeSet(d Decoder, x interface{}) (interface{}, error) {
|
||||
tagged := x.(TaggedValue)
|
||||
if !IsGenericArray(tagged.Value) {
|
||||
return nil, NewTransitError("Set contents are not an array.", tagged)
|
||||
}
|
||||
values := (tagged.Value).([]interface{})
|
||||
result := NewSet(values)
|
||||
return result, nil
|
||||
}
|
||||
|
||||
// DecodeList decodes a transit list into a Go list.
|
||||
func DecodeList(d Decoder, x interface{}) (interface{}, error) {
|
||||
tagged := x.(TaggedValue)
|
||||
if !IsGenericArray(tagged.Value) {
|
||||
return nil, NewTransitError("List contents are not an array.", tagged)
|
||||
}
|
||||
values := (tagged.Value).([]interface{})
|
||||
result := list.New()
|
||||
for _, item := range values {
|
||||
result.PushBack(item)
|
||||
}
|
||||
return result, nil
|
||||
}
|
||||
|
||||
// DecodeQuote decodes a transit quoted value by simply returning the value.
|
||||
func DecodeQuote(d Decoder, x interface{}) (interface{}, error) {
|
||||
tagged := x.(TaggedValue)
|
||||
return tagged.Value, nil
|
||||
}
|
||||
|
||||
// DecodeRFC3339 decodes a time value into a Go time instance.
|
||||
// TBD not 100% this covers all possible values.
|
||||
func DecodeRFC3339(d Decoder, x interface{}) (interface{}, error) {
|
||||
s := x.(string)
|
||||
var result, err = time.Parse(time.RFC3339Nano, s)
|
||||
return result, err
|
||||
}
|
||||
|
||||
// DecodeTime decodes a time value represended as millis since 1970.
|
||||
func DecodeTime(d Decoder, x interface{}) (interface{}, error) {
|
||||
s := x.(string)
|
||||
var millis, _ = strconv.ParseInt(s, 10, 64)
|
||||
seconds := millis / 1000
|
||||
remainder_millis := millis - (seconds * 1000)
|
||||
nanos := remainder_millis * 1000000
|
||||
result := time.Unix(seconds, nanos).UTC()
|
||||
return result, nil
|
||||
}
|
||||
|
||||
// DecodeBoolean decodes a transit boolean into a Go bool.
|
||||
func DecodeBoolean(d Decoder, x interface{}) (interface{}, error) {
|
||||
s := x.(string)
|
||||
if s == "t" {
|
||||
return true, nil
|
||||
} else if s == "f" {
|
||||
return false, nil
|
||||
} else {
|
||||
return nil, &TransitError{Message: "Unknown boolean value."}
|
||||
}
|
||||
}
|
||||
|
||||
// DecodeBigInteger decodes a transit big integer into a Go big.Int.
|
||||
func DecodeBigInteger(d Decoder, x interface{}) (interface{}, error) {
|
||||
s := x.(string)
|
||||
result := new(big.Int)
|
||||
_, good := result.SetString(s, 10)
|
||||
if !good {
|
||||
return nil, &TransitError{Message: "Unable to part big integer: " + s}
|
||||
}
|
||||
return result, nil
|
||||
}
|
||||
|
||||
// DecodeInteger decodes a transit integer into a plain Go int64
|
||||
func DecodeInteger(d Decoder, x interface{}) (interface{}, error) {
|
||||
s := x.(string)
|
||||
result, err := strconv.ParseInt(s, 10, 64)
|
||||
return result, err
|
||||
}
|
||||
|
||||
func newRational(a, b *big.Int) *big.Rat {
|
||||
var r = big.NewRat(1, 1)
|
||||
r.SetFrac(a, b)
|
||||
return r
|
||||
}
|
||||
|
||||
func toBigInt(x interface{}) (*big.Int, error) {
|
||||
switch v := x.(type) {
|
||||
default:
|
||||
return nil, NewTransitError("Not a numeric value", v)
|
||||
case *big.Int:
|
||||
return v, nil
|
||||
case int64:
|
||||
return big.NewInt(v), nil
|
||||
}
|
||||
}
|
||||
|
||||
// DecodeRatio decodes a transit ratio into a Go big.Rat.
|
||||
func DecodeRatio(d Decoder, x interface{}) (interface{}, error) {
|
||||
tagged := x.(TaggedValue)
|
||||
if !IsGenericArray(tagged.Value) {
|
||||
return nil, NewTransitError("Ratio contents are not an array.", tagged)
|
||||
}
|
||||
|
||||
values := (tagged.Value).([]interface{})
|
||||
|
||||
if len(values) != 2 {
|
||||
return nil, NewTransitError("Ratio contents does not contain 2 elements.", tagged)
|
||||
}
|
||||
|
||||
a, err := toBigInt(values[0])
|
||||
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
b, err := toBigInt(values[1])
|
||||
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
result := newRational(a, b)
|
||||
return *result, nil
|
||||
}
|
||||
|
||||
// DecodeRune decodes a transit char.
|
||||
func DecodeRune(d Decoder, x interface{}) (interface{}, error) {
|
||||
s := x.(string)
|
||||
return rune(s[0]), nil
|
||||
}
|
||||
|
||||
// DecodeFloat decodes the value into a float.
|
||||
func DecodeFloat(d Decoder, x interface{}) (interface{}, error) {
|
||||
s := x.(string)
|
||||
return strconv.ParseFloat(s, 64)
|
||||
}
|
||||
|
||||
// DecodeDecimal decodes a transit big decimal into decimal.Decimal.
|
||||
func DecodeDecimal(d Decoder, x interface{}) (interface{}, error) {
|
||||
s := x.(string)
|
||||
return decimal.NewFromString((s))
|
||||
}
|
||||
|
||||
// DecodeRatio decodes a transit null/nil.
|
||||
func DecodeNil(d Decoder, x interface{}) (interface{}, error) {
|
||||
return nil, nil
|
||||
}
|
||||
|
||||
// DecodeRatio decodes a transit base64 encoded byte array into a
|
||||
// Go byte array.
|
||||
func DecodeByte(d Decoder, x interface{}) (interface{}, error) {
|
||||
s := x.(string)
|
||||
return base64.StdEncoding.DecodeString(s)
|
||||
}
|
||||
|
||||
// DecodeLink decodes a transit link into an instance of Link.
|
||||
func DecodeLink(d Decoder, x interface{}) (interface{}, error) {
|
||||
tv := x.(TaggedValue)
|
||||
v := tv.Value.(map[interface{}]interface{})
|
||||
l := NewLink()
|
||||
l.Href = v["href"].(*TUri)
|
||||
l.Name = v["name"].(string)
|
||||
l.Rel = v["rel"].(string)
|
||||
l.Prompt = v["prompt"].(string)
|
||||
l.Render = v["render"].(string)
|
||||
return l, nil
|
||||
}
|
||||
|
||||
// DecodeURI decodes a transit URI into an instance of TUri.
|
||||
func DecodeURI(d Decoder, x interface{}) (interface{}, error) {
|
||||
s := x.(string)
|
||||
return NewTUri(s), nil
|
||||
}
|
||||
|
||||
// DecodeUUID decodes a transit UUID into an instance of net/UUID
|
||||
func DecodeUUID(d Decoder, x interface{}) (interface{}, error) {
|
||||
s := x.(string)
|
||||
var u = uuid.Parse(s)
|
||||
if u == nil {
|
||||
return nil, &TransitError{Message: "Unable to parse uuid [" + s + "]"}
|
||||
}
|
||||
return u, nil
|
||||
}
|
||||
|
||||
// DecodeSpecialNumber decodes NaN, INF and -INF into their Go equivalents.
|
||||
func DecodeSpecialNumber(d Decoder, x interface{}) (interface{}, error) {
|
||||
tag := x.(string)
|
||||
if tag == "NaN" {
|
||||
return math.NaN(), nil
|
||||
} else if tag == "INF" {
|
||||
return math.Inf(1), nil
|
||||
} else if tag == "-INF" {
|
||||
return math.Inf(-1), nil
|
||||
} else {
|
||||
return nil, &TransitError{Message: "Bad special number:"}
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user