mirror of
https://github.com/d0zingcat/gocryptotrader.git
synced 2026-05-13 15:09:42 +00:00
* Kucoin: Rename WsSpotTicker => WsSnapshot * Kucoin: Replace kucoinNumber => types.Number * Okcoin: Convert to types.Number * Gateio: Convert to types.Number * Okx: Convert to types.Number
79 lines
2.1 KiB
Go
79 lines
2.1 KiB
Go
package types
|
|
|
|
import (
|
|
"errors"
|
|
"fmt"
|
|
"strconv"
|
|
|
|
"github.com/shopspring/decimal"
|
|
)
|
|
|
|
var errInvalidNumberValue = errors.New("invalid value for Number type")
|
|
|
|
// Number represents a floating point number, and implements json.Unmarshaller and json.Marshaller
|
|
type Number float64
|
|
|
|
// UnmarshalJSON implements json.Unmarshaler
|
|
func (f *Number) UnmarshalJSON(data []byte) error {
|
|
switch c := data[0]; c { // From json.decode literalInterface
|
|
case 'n', 't', 'f': // null, true, false
|
|
return fmt.Errorf("%w: %s", errInvalidNumberValue, data)
|
|
case '"': // string
|
|
if len(data) < 2 || data[len(data)-1] != '"' {
|
|
return fmt.Errorf("%w: %s", errInvalidNumberValue, data)
|
|
}
|
|
data = data[1 : len(data)-1] // Naive Unquote
|
|
default: // Should be a number
|
|
if c != '-' && (c < '0' || c > '9') { // Invalid json syntax
|
|
return fmt.Errorf("%w: %s", errInvalidNumberValue, data)
|
|
}
|
|
}
|
|
|
|
if len(data) == 0 {
|
|
*f = Number(0)
|
|
return nil
|
|
}
|
|
|
|
val, err := strconv.ParseFloat(string(data), 64)
|
|
if err != nil {
|
|
return fmt.Errorf("%w: %s", errInvalidNumberValue, data) // We don't use err; We know it's not valid and errInvalidNumberValue is clearer
|
|
}
|
|
|
|
*f = Number(val)
|
|
|
|
return nil
|
|
}
|
|
|
|
// MarshalJSON implements json.Marshaler by formatting to a json string
|
|
// 1337.37 will marshal to "1337.37"
|
|
// 0 will marshal to an empty string: ""
|
|
func (f Number) MarshalJSON() ([]byte, error) {
|
|
if f == 0 {
|
|
return []byte(`""`), nil
|
|
}
|
|
val := strconv.FormatFloat(float64(f), 'f', -1, 64)
|
|
return []byte(`"` + val + `"`), nil
|
|
}
|
|
|
|
// Float64 returns the underlying float64
|
|
func (f Number) Float64() float64 {
|
|
return float64(f)
|
|
}
|
|
|
|
// Int64 returns the truncated integer component of the number
|
|
func (f Number) Int64() int64 {
|
|
// It's likely this is sufficient, since Numbers probably have not had floating point math performed on them
|
|
// However if issues arise then we can switch to math.Round
|
|
return int64(f)
|
|
}
|
|
|
|
// Decimal returns a decimal.Decimal
|
|
func (f Number) Decimal() decimal.Decimal {
|
|
return decimal.NewFromFloat(float64(f))
|
|
}
|
|
|
|
// String returns a string representation of the number
|
|
func (f Number) String() string {
|
|
return strconv.FormatFloat(float64(f), 'f', -1, 64)
|
|
}
|