github.com/chrislusf/greenpack@v3.7.1-0.20170911073826-ad5bd10b7c47+incompatible/msgp/number.go (about)

     1  package msgp
     2  
     3  import (
     4  	"math"
     5  	"strconv"
     6  )
     7  
     8  // The portable parts of the Number implementation
     9  
    10  // Number can be
    11  // an int64, uint64, float32,
    12  // or float64 internally.
    13  // It can decode itself
    14  // from any of the native
    15  // messagepack number types.
    16  // The zero-value of Number
    17  // is Int(0). Using the equality
    18  // operator with Number compares
    19  // both the type and the value
    20  // of the number.
    21  type Number struct {
    22  	// internally, this
    23  	// is just a tagged union.
    24  	// the raw bits of the number
    25  	// are stored the same way regardless.
    26  	bits uint64
    27  	typ  Type
    28  }
    29  
    30  // AsInt sets the number to an int64.
    31  func (n *Number) AsInt(i int64) {
    32  
    33  	// we always store int(0)
    34  	// as {0, InvalidType} in
    35  	// order to preserve
    36  	// the behavior of the == operator
    37  	if i == 0 {
    38  		n.typ = InvalidType
    39  		n.bits = 0
    40  		return
    41  	}
    42  
    43  	n.typ = IntType
    44  	n.bits = uint64(i)
    45  }
    46  
    47  // AsUint sets the number to a uint64.
    48  func (n *Number) AsUint(u uint64) {
    49  	n.typ = UintType
    50  	n.bits = u
    51  }
    52  
    53  // AsFloat32 sets the value of the number
    54  // to a float32.
    55  func (n *Number) AsFloat32(f float32) {
    56  	n.typ = Float32Type
    57  	n.bits = uint64(math.Float32bits(f))
    58  }
    59  
    60  // AsFloat64 sets the value of the
    61  // number to a float64.
    62  func (n *Number) AsFloat64(f float64) {
    63  	n.typ = Float64Type
    64  	n.bits = math.Float64bits(f)
    65  }
    66  
    67  // Int casts the number as an int64, and
    68  // returns whether or not that was the
    69  // underlying type.
    70  func (n *Number) Int() (int64, bool) {
    71  	return int64(n.bits), n.typ == IntType || n.typ == InvalidType
    72  }
    73  
    74  // Uint casts the number as a uint64, and returns
    75  // whether or not that was the underlying type.
    76  func (n *Number) Uint() (uint64, bool) {
    77  	return n.bits, n.typ == UintType
    78  }
    79  
    80  // Float casts the number to a float64, and
    81  // returns whether or not that was the underlying
    82  // type (either a float64 or a float32).
    83  func (n *Number) Float() (float64, bool) {
    84  	switch n.typ {
    85  	case Float32Type:
    86  		return float64(math.Float32frombits(uint32(n.bits))), true
    87  	case Float64Type:
    88  		return math.Float64frombits(n.bits), true
    89  	default:
    90  		return 0.0, false
    91  	}
    92  }
    93  
    94  // Type will return one of:
    95  // Float64Type, Float32Type, UintType, or IntType.
    96  func (n *Number) Type() Type {
    97  	if n.typ == InvalidType {
    98  		return IntType
    99  	}
   100  	return n.typ
   101  }
   102  
   103  // DecodeMsg implements msgp.Decodable
   104  func (n *Number) DecodeMsg(r *Reader) error {
   105  	typ, err := r.NextType()
   106  	if err != nil {
   107  		return err
   108  	}
   109  	switch typ {
   110  	case Float32Type:
   111  		f, err := r.ReadFloat32()
   112  		if err != nil {
   113  			return err
   114  		}
   115  		n.AsFloat32(f)
   116  		return nil
   117  	case Float64Type:
   118  		f, err := r.ReadFloat64()
   119  		if err != nil {
   120  			return err
   121  		}
   122  		n.AsFloat64(f)
   123  		return nil
   124  	case IntType:
   125  		i, err := r.ReadInt64()
   126  		if err != nil {
   127  			return err
   128  		}
   129  		n.AsInt(i)
   130  		return nil
   131  	case UintType:
   132  		u, err := r.ReadUint64()
   133  		if err != nil {
   134  			return err
   135  		}
   136  		n.AsUint(u)
   137  		return nil
   138  	default:
   139  		return TypeError{Encoded: typ, Method: IntType}
   140  	}
   141  }
   142  
   143  // UnmarshalMsg implements msgp.Unmarshaler
   144  func (n *Number) UnmarshalMsg(b []byte) ([]byte, error) {
   145  	var nbs *NilBitsStack
   146  	typ := NextType(b)
   147  	switch typ {
   148  	case IntType:
   149  		i, o, err := nbs.ReadInt64Bytes(b)
   150  		if err != nil {
   151  			return b, err
   152  		}
   153  		n.AsInt(i)
   154  		return o, nil
   155  	case UintType:
   156  		u, o, err := nbs.ReadUint64Bytes(b)
   157  		if err != nil {
   158  			return b, err
   159  		}
   160  		n.AsUint(u)
   161  		return o, nil
   162  	case Float64Type:
   163  		f, o, err := nbs.ReadFloat64Bytes(b)
   164  		if err != nil {
   165  			return b, err
   166  		}
   167  		n.AsFloat64(f)
   168  		return o, nil
   169  	case Float32Type:
   170  		f, o, err := nbs.ReadFloat32Bytes(b)
   171  		if err != nil {
   172  			return b, err
   173  		}
   174  		n.AsFloat32(f)
   175  		return o, nil
   176  	default:
   177  		return b, TypeError{Method: IntType, Encoded: typ}
   178  	}
   179  }
   180  
   181  // MarshalMsg implements msgp.Marshaler
   182  func (n *Number) MarshalMsg(b []byte) ([]byte, error) {
   183  	switch n.typ {
   184  	case IntType:
   185  		return AppendInt64(b, int64(n.bits)), nil
   186  	case UintType:
   187  		return AppendUint64(b, uint64(n.bits)), nil
   188  	case Float64Type:
   189  		return AppendFloat64(b, math.Float64frombits(n.bits)), nil
   190  	case Float32Type:
   191  		return AppendFloat32(b, math.Float32frombits(uint32(n.bits))), nil
   192  	default:
   193  		return AppendInt64(b, 0), nil
   194  	}
   195  }
   196  
   197  // EncodeMsg implements msgp.Encodable
   198  func (n *Number) EncodeMsg(w *Writer) error {
   199  	switch n.typ {
   200  	case IntType:
   201  		return w.WriteInt64(int64(n.bits))
   202  	case UintType:
   203  		return w.WriteUint64(n.bits)
   204  	case Float64Type:
   205  		return w.WriteFloat64(math.Float64frombits(n.bits))
   206  	case Float32Type:
   207  		return w.WriteFloat32(math.Float32frombits(uint32(n.bits)))
   208  	default:
   209  		return w.WriteInt64(0)
   210  	}
   211  }
   212  
   213  // Msgsize implements msgp.Sizer
   214  func (n *Number) Msgsize() int {
   215  	switch n.typ {
   216  	case Float32Type:
   217  		return Float32Size
   218  	case Float64Type:
   219  		return Float64Size
   220  	case IntType:
   221  		return Int64Size
   222  	case UintType:
   223  		return Uint64Size
   224  	default:
   225  		return 1 // fixint(0)
   226  	}
   227  }
   228  
   229  // MarshalJSON implements json.Marshaler
   230  func (n *Number) MarshalJSON() ([]byte, error) {
   231  	t := n.Type()
   232  	if t == InvalidType {
   233  		return []byte{'0'}, nil
   234  	}
   235  	out := make([]byte, 0, 32)
   236  	switch t {
   237  	case Float32Type, Float64Type:
   238  		f, _ := n.Float()
   239  		return strconv.AppendFloat(out, f, 'f', -1, 64), nil
   240  	case IntType:
   241  		i, _ := n.Int()
   242  		return strconv.AppendInt(out, i, 10), nil
   243  	case UintType:
   244  		u, _ := n.Uint()
   245  		return strconv.AppendUint(out, u, 10), nil
   246  	default:
   247  		panic("(*Number).typ is invalid")
   248  	}
   249  }
   250  
   251  // String implements fmt.Stringer
   252  func (n *Number) String() string {
   253  	switch n.typ {
   254  	case InvalidType:
   255  		return "0"
   256  	case Float32Type, Float64Type:
   257  		f, _ := n.Float()
   258  		return strconv.FormatFloat(f, 'f', -1, 64)
   259  	case IntType:
   260  		i, _ := n.Int()
   261  		return strconv.FormatInt(i, 10)
   262  	case UintType:
   263  		u, _ := n.Uint()
   264  		return strconv.FormatUint(u, 10)
   265  	default:
   266  		panic("(*Number).typ is invalid")
   267  	}
   268  }