blob: 73abb93d22e52f4f07b0ba08f24b76ef79fa52d4 [file] [log] [blame]
// Copyright 2016-2019 Alex Stocks
//
// 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 hessian
import (
"encoding/binary"
"math"
)
import (
perrors "github.com/pkg/errors"
)
/////////////////////////////////////////
// Double
/////////////////////////////////////////
// # 64-bit IEEE double
// ::= 'D' b7 b6 b5 b4 b3 b2 b1 b0
// ::= x5b # 0.0
// ::= x5c # 1.0
// ::= x5d b0 # byte cast to double (-128.0 to 127.0)
// ::= x5e b1 b0 # short cast to double
// ::= x5f b3 b2 b1 b0 # 32-bit float cast to double
func encFloat(b []byte, v float64) []byte {
fv := float64(int64(v))
if fv == v {
iv := int64(v)
switch iv {
case 0:
return encByte(b, BC_DOUBLE_ZERO)
case 1:
return encByte(b, BC_DOUBLE_ONE)
}
if iv >= -0x80 && iv < 0x80 {
return encByte(b, BC_DOUBLE_BYTE, byte(iv))
} else if iv >= -0x8000 && iv < 0x8000 {
return encByte(b, BC_DOUBLE_BYTE, byte(iv>>8), byte(iv))
}
goto END
}
END:
bits := math.Float64bits(v)
return encByte(b, BC_DOUBLE, byte(bits>>56), byte(bits>>48), byte(bits>>40),
byte(bits>>32), byte(bits>>24), byte(bits>>16), byte(bits>>8), byte(bits))
}
/////////////////////////////////////////
// Double
/////////////////////////////////////////
// # 64-bit IEEE double
// ::= 'D' b7 b6 b5 b4 b3 b2 b1 b0
// ::= x5b # 0.0
// ::= x5c # 1.0
// ::= x5d b0 # byte cast to double (-128.0 to 127.0)
// ::= x5e b1 b0 # short cast to double
// ::= x5f b3 b2 b1 b0 # 32-bit float cast to double
func (d *Decoder) decDouble(flag int32) (interface{}, error) {
var (
err error
tag byte
)
if flag != TAG_READ {
tag = byte(flag)
} else {
tag, _ = d.readByte()
}
switch tag {
case BC_LONG_INT:
return d.decInt32(TAG_READ)
case BC_DOUBLE_ZERO:
return float64(0), nil
case BC_DOUBLE_ONE:
return float64(1), nil
case BC_DOUBLE_BYTE:
var i8 int8
err = binary.Read(d.reader, binary.BigEndian, &i8)
return float64(i8), perrors.WithStack(err)
case BC_DOUBLE_SHORT:
var i16 int16
err = binary.Read(d.reader, binary.BigEndian, &i16)
return float64(i16), perrors.WithStack(err)
case BC_DOUBLE_MILL:
var i32 int32
err = binary.Read(d.reader, binary.BigEndian, &i32)
return float64(i32) / 1000, perrors.WithStack(err)
case BC_DOUBLE:
var f64 float64
err = binary.Read(d.reader, binary.BigEndian, &f64)
return f64, perrors.WithStack(err)
}
return nil, perrors.Errorf("decDouble parse double wrong tag:%d-%#x", int(tag), tag)
}