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

     1  package msgp
     2  
     3  import (
     4  	"math"
     5  	"reflect"
     6  	"time"
     7  )
     8  
     9  // ensure 'sz' extra bytes in 'b' btw len(b) and cap(b)
    10  func ensure(b []byte, sz int) ([]byte, int) {
    11  	l := len(b)
    12  	c := cap(b)
    13  	if c-l < sz {
    14  		o := make([]byte, (2*c)+sz) // exponential growth
    15  		n := copy(o, b)
    16  		return o[:n+sz], n
    17  	}
    18  	return b[:l+sz], l
    19  }
    20  
    21  // AppendMapHeader appends a map header with the
    22  // given size to the slice
    23  func AppendMapHeader(b []byte, sz uint32) []byte {
    24  	switch {
    25  	case sz <= 15:
    26  		return append(b, wfixmap(uint8(sz)))
    27  
    28  	case sz <= math.MaxUint16:
    29  		o, n := ensure(b, 3)
    30  		prefixu16(o[n:], mmap16, uint16(sz))
    31  		return o
    32  
    33  	default:
    34  		o, n := ensure(b, 5)
    35  		prefixu32(o[n:], mmap32, sz)
    36  		return o
    37  	}
    38  }
    39  
    40  // AppendArrayHeader appends an array header with
    41  // the given size to the slice
    42  func AppendArrayHeader(b []byte, sz uint32) []byte {
    43  	switch {
    44  	case sz <= 15:
    45  		return append(b, wfixarray(uint8(sz)))
    46  
    47  	case sz <= math.MaxUint16:
    48  		o, n := ensure(b, 3)
    49  		prefixu16(o[n:], marray16, uint16(sz))
    50  		return o
    51  
    52  	default:
    53  		o, n := ensure(b, 5)
    54  		prefixu32(o[n:], marray32, sz)
    55  		return o
    56  	}
    57  }
    58  
    59  // AppendNil appends a 'nil' byte to the slice
    60  func AppendNil(b []byte) []byte { return append(b, mnil) }
    61  
    62  // AppendFloat64 appends a float64 to the slice
    63  func AppendFloat64(b []byte, f float64) []byte {
    64  	o, n := ensure(b, Float64Size)
    65  	prefixu64(o[n:], mfloat64, math.Float64bits(f))
    66  	return o
    67  }
    68  
    69  // AppendFloat32 appends a float32 to the slice
    70  func AppendFloat32(b []byte, f float32) []byte {
    71  	o, n := ensure(b, Float32Size)
    72  	prefixu32(o[n:], mfloat32, math.Float32bits(f))
    73  	return o
    74  }
    75  
    76  // AppendInt64 appends an int64 to the slice
    77  func AppendInt64(b []byte, i int64) []byte {
    78  	if i >= 0 {
    79  		switch {
    80  		case i <= math.MaxInt8:
    81  			return append(b, wfixint(uint8(i)))
    82  		case i <= math.MaxInt16:
    83  			o, n := ensure(b, 3)
    84  			putMint16(o[n:], int16(i))
    85  			return o
    86  		case i <= math.MaxInt32:
    87  			o, n := ensure(b, 5)
    88  			putMint32(o[n:], int32(i))
    89  			return o
    90  		default:
    91  			o, n := ensure(b, 9)
    92  			putMint64(o[n:], i)
    93  			return o
    94  		}
    95  	}
    96  	switch {
    97  	case i >= -32:
    98  		return append(b, wnfixint(int8(i)))
    99  	case i >= math.MinInt8:
   100  		o, n := ensure(b, 2)
   101  		putMint8(o[n:], int8(i))
   102  		return o
   103  	case i >= math.MinInt16:
   104  		o, n := ensure(b, 3)
   105  		putMint16(o[n:], int16(i))
   106  		return o
   107  	case i >= math.MinInt32:
   108  		o, n := ensure(b, 5)
   109  		putMint32(o[n:], int32(i))
   110  		return o
   111  	default:
   112  		o, n := ensure(b, 9)
   113  		putMint64(o[n:], i)
   114  		return o
   115  	}
   116  }
   117  
   118  // AppendInt appends an int to the slice
   119  func AppendInt(b []byte, i int) []byte { return AppendInt64(b, int64(i)) }
   120  
   121  // AppendInt8 appends an int8 to the slice
   122  func AppendInt8(b []byte, i int8) []byte { return AppendInt64(b, int64(i)) }
   123  
   124  // AppendInt16 appends an int16 to the slice
   125  func AppendInt16(b []byte, i int16) []byte { return AppendInt64(b, int64(i)) }
   126  
   127  // AppendInt32 appends an int32 to the slice
   128  func AppendInt32(b []byte, i int32) []byte { return AppendInt64(b, int64(i)) }
   129  
   130  // AppendUint64 appends a uint64 to the slice
   131  func AppendUint64(b []byte, u uint64) []byte {
   132  	switch {
   133  	case u <= (1<<7)-1:
   134  		return append(b, wfixint(uint8(u)))
   135  
   136  	case u <= math.MaxUint8:
   137  		o, n := ensure(b, 2)
   138  		putMuint8(o[n:], uint8(u))
   139  		return o
   140  
   141  	case u <= math.MaxUint16:
   142  		o, n := ensure(b, 3)
   143  		putMuint16(o[n:], uint16(u))
   144  		return o
   145  
   146  	case u <= math.MaxUint32:
   147  		o, n := ensure(b, 5)
   148  		putMuint32(o[n:], uint32(u))
   149  		return o
   150  
   151  	default:
   152  		o, n := ensure(b, 9)
   153  		putMuint64(o[n:], u)
   154  		return o
   155  
   156  	}
   157  }
   158  
   159  // AppendUint appends a uint to the slice
   160  func AppendUint(b []byte, u uint) []byte { return AppendUint64(b, uint64(u)) }
   161  
   162  // AppendUint8 appends a uint8 to the slice
   163  func AppendUint8(b []byte, u uint8) []byte { return AppendUint64(b, uint64(u)) }
   164  
   165  // AppendByte is analogous to AppendUint8
   166  func AppendByte(b []byte, u byte) []byte { return AppendUint8(b, uint8(u)) }
   167  
   168  // AppendUint16 appends a uint16 to the slice
   169  func AppendUint16(b []byte, u uint16) []byte { return AppendUint64(b, uint64(u)) }
   170  
   171  // AppendUint32 appends a uint32 to the slice
   172  func AppendUint32(b []byte, u uint32) []byte { return AppendUint64(b, uint64(u)) }
   173  
   174  // AppendBytes appends bytes to the slice as MessagePack 'bin' data
   175  func AppendBytes(b []byte, bts []byte) []byte {
   176  	sz := len(bts)
   177  	var o []byte
   178  	var n int
   179  	switch {
   180  	case sz <= math.MaxUint8:
   181  		o, n = ensure(b, 2+sz)
   182  		prefixu8(o[n:], mbin8, uint8(sz))
   183  		n += 2
   184  	case sz <= math.MaxUint16:
   185  		o, n = ensure(b, 3+sz)
   186  		prefixu16(o[n:], mbin16, uint16(sz))
   187  		n += 3
   188  	default:
   189  		o, n = ensure(b, 5+sz)
   190  		prefixu32(o[n:], mbin32, uint32(sz))
   191  		n += 5
   192  	}
   193  	return o[:n+copy(o[n:], bts)]
   194  }
   195  
   196  // AppendBool appends a bool to the slice
   197  func AppendBool(b []byte, t bool) []byte {
   198  	if t {
   199  		return append(b, mtrue)
   200  	}
   201  	return append(b, mfalse)
   202  }
   203  
   204  // AppendString appends a string as a MessagePack 'str' to the slice
   205  func AppendString(b []byte, s string) []byte {
   206  	sz := len(s)
   207  	var n int
   208  	var o []byte
   209  	switch {
   210  	case sz <= 31:
   211  		o, n = ensure(b, 1+sz)
   212  		o[n] = wfixstr(uint8(sz))
   213  		n++
   214  	case sz <= math.MaxUint8:
   215  		o, n = ensure(b, 2+sz)
   216  		prefixu8(o[n:], mstr8, uint8(sz))
   217  		n += 2
   218  	case sz <= math.MaxUint16:
   219  		o, n = ensure(b, 3+sz)
   220  		prefixu16(o[n:], mstr16, uint16(sz))
   221  		n += 3
   222  	default:
   223  		o, n = ensure(b, 5+sz)
   224  		prefixu32(o[n:], mstr32, uint32(sz))
   225  		n += 5
   226  	}
   227  	return o[:n+copy(o[n:], s)]
   228  }
   229  
   230  // AppendStringFromBytes appends a []byte
   231  // as a MessagePack 'str' to the slice 'b.'
   232  func AppendStringFromBytes(b []byte, str []byte) []byte {
   233  	sz := len(str)
   234  	var n int
   235  	var o []byte
   236  	switch {
   237  	case sz <= 31:
   238  		o, n = ensure(b, 1+sz)
   239  		o[n] = wfixstr(uint8(sz))
   240  		n++
   241  	case sz <= math.MaxUint8:
   242  		o, n = ensure(b, 2+sz)
   243  		prefixu8(o[n:], mstr8, uint8(sz))
   244  		n += 2
   245  	case sz <= math.MaxUint16:
   246  		o, n = ensure(b, 3+sz)
   247  		prefixu16(o[n:], mstr16, uint16(sz))
   248  		n += 3
   249  	default:
   250  		o, n = ensure(b, 5+sz)
   251  		prefixu32(o[n:], mstr32, uint32(sz))
   252  		n += 5
   253  	}
   254  	return o[:n+copy(o[n:], str)]
   255  }
   256  
   257  // AppendComplex64 appends a complex64 to the slice as a MessagePack extension
   258  func AppendComplex64(b []byte, c complex64) []byte {
   259  	o, n := ensure(b, Complex64Size)
   260  	o[n] = mfixext8
   261  	o[n+1] = Complex64Extension
   262  	big.PutUint32(o[n+2:], math.Float32bits(real(c)))
   263  	big.PutUint32(o[n+6:], math.Float32bits(imag(c)))
   264  	return o
   265  }
   266  
   267  // AppendComplex128 appends a complex128 to the slice as a MessagePack extension
   268  func AppendComplex128(b []byte, c complex128) []byte {
   269  	o, n := ensure(b, Complex128Size)
   270  	o[n] = mfixext16
   271  	o[n+1] = Complex128Extension
   272  	big.PutUint64(o[n+2:], math.Float64bits(real(c)))
   273  	big.PutUint64(o[n+10:], math.Float64bits(imag(c)))
   274  	return o
   275  }
   276  
   277  // AppendTime appends a time.Time to the slice as a MessagePack extension
   278  func AppendTime(b []byte, t time.Time) []byte {
   279  	o, n := ensure(b, TimeSize)
   280  	t = t.UTC()
   281  	o[n] = mext8
   282  	o[n+1] = 12
   283  	o[n+2] = TimeExtension
   284  	putUnix(o[n+3:], t.Unix(), int32(t.Nanosecond()))
   285  	return o
   286  }
   287  
   288  // AppendMapStrStr appends a map[string]string to the slice
   289  // as a MessagePack map with 'str'-type keys and values
   290  func AppendMapStrStr(b []byte, m map[string]string) []byte {
   291  	sz := uint32(len(m))
   292  	b = AppendMapHeader(b, sz)
   293  	for key, val := range m {
   294  		b = AppendString(b, key)
   295  		b = AppendString(b, val)
   296  	}
   297  	return b
   298  }
   299  
   300  // AppendMapStrIntf appends a map[string]interface{} to the slice
   301  // as a MessagePack map with 'str'-type keys.
   302  func AppendMapStrIntf(b []byte, m map[string]interface{}) ([]byte, error) {
   303  	sz := uint32(len(m))
   304  	b = AppendMapHeader(b, sz)
   305  	var err error
   306  	for key, val := range m {
   307  		b = AppendString(b, key)
   308  		b, err = AppendIntf(b, val)
   309  		if err != nil {
   310  			return b, err
   311  		}
   312  	}
   313  	return b, nil
   314  }
   315  
   316  // AppendMapStrSomething appends a map[string]* to the slice
   317  // as a MessagePack map with 'str'-type keys. * must be
   318  // serializable by AppendIntf().
   319  func AppendMapStrSomething(b []byte, m reflect.Value) ([]byte, error) {
   320  
   321  	keys := m.MapKeys()
   322  	sz := uint32(len(keys))
   323  	if sz == 0 {
   324  		b = AppendMapHeader(b, sz)
   325  		return b, nil
   326  	}
   327  	var err error
   328  	for i, key := range keys {
   329  		if i == 0 {
   330  			if key.Type().Kind() != reflect.String {
   331  				return b, &ErrUnsupportedType{T: m.Type()}
   332  			}
   333  			// lazy because we try hard not to write
   334  			// half a value to b and then error out.
   335  			b = AppendMapHeader(b, sz)
   336  		}
   337  
   338  		b = AppendString(b, key.String())
   339  		val := m.MapIndex(key)
   340  		b, err = AppendIntf(b, val.Interface())
   341  		if err != nil {
   342  			return b, err
   343  		}
   344  	}
   345  	return b, nil
   346  }
   347  
   348  // AppendIntf appends the concrete type of 'i' to the
   349  // provided []byte. 'i' must be one of the following:
   350  //  - 'nil'
   351  //  - A bool, float, string, []byte, int, uint, or complex
   352  //  - A map[string]interface{} or map[string]string
   353  //  - A []T, where T is another supported type
   354  //  - A *T, where T is another supported type
   355  //  - A type that satisfieds the msgp.Marshaler interface
   356  //  - A type that satisfies the msgp.Extension interface
   357  func AppendIntf(b []byte, i interface{}) ([]byte, error) {
   358  	if i == nil {
   359  		return AppendNil(b), nil
   360  	}
   361  
   362  	// all the concrete types
   363  	// for which we have methods
   364  	switch i := i.(type) {
   365  	case Marshaler:
   366  		return i.MarshalMsg(b)
   367  	case Extension:
   368  		return AppendExtension(b, i)
   369  	case bool:
   370  		return AppendBool(b, i), nil
   371  	case float32:
   372  		return AppendFloat32(b, i), nil
   373  	case float64:
   374  		return AppendFloat64(b, i), nil
   375  	case complex64:
   376  		return AppendComplex64(b, i), nil
   377  	case complex128:
   378  		return AppendComplex128(b, i), nil
   379  	case string:
   380  		return AppendString(b, i), nil
   381  	case []byte:
   382  		return AppendBytes(b, i), nil
   383  	case int8:
   384  		return AppendInt8(b, i), nil
   385  	case int16:
   386  		return AppendInt16(b, i), nil
   387  	case int32:
   388  		return AppendInt32(b, i), nil
   389  	case int64:
   390  		return AppendInt64(b, i), nil
   391  	case int:
   392  		return AppendInt64(b, int64(i)), nil
   393  	case uint:
   394  		return AppendUint64(b, uint64(i)), nil
   395  	case uint8:
   396  		return AppendUint8(b, i), nil
   397  	case uint16:
   398  		return AppendUint16(b, i), nil
   399  	case uint32:
   400  		return AppendUint32(b, i), nil
   401  	case uint64:
   402  		return AppendUint64(b, i), nil
   403  	case time.Time:
   404  		return AppendTime(b, i), nil
   405  	case map[string]interface{}:
   406  		return AppendMapStrIntf(b, i)
   407  	case map[string]string:
   408  		return AppendMapStrStr(b, i), nil
   409  	case []interface{}:
   410  		b = AppendArrayHeader(b, uint32(len(i)))
   411  		var err error
   412  		for _, k := range i {
   413  			b, err = AppendIntf(b, k)
   414  			if err != nil {
   415  				return b, err
   416  			}
   417  		}
   418  		return b, nil
   419  	}
   420  
   421  	var err error
   422  	v := reflect.ValueOf(i)
   423  	switch v.Kind() {
   424  	case reflect.Array, reflect.Slice:
   425  		l := v.Len()
   426  		b = AppendArrayHeader(b, uint32(l))
   427  		for i := 0; i < l; i++ {
   428  			b, err = AppendIntf(b, v.Index(i).Interface())
   429  			if err != nil {
   430  				return b, err
   431  			}
   432  		}
   433  		return b, nil
   434  	case reflect.Ptr:
   435  		if v.IsNil() {
   436  			return AppendNil(b), err
   437  		}
   438  		b, err = AppendIntf(b, v.Elem().Interface())
   439  		return b, err
   440  
   441  	case reflect.Map:
   442  		return AppendMapStrSomething(b, v)
   443  	default:
   444  		return b, &ErrUnsupportedType{T: v.Type()}
   445  	}
   446  }
   447  
   448  // AppendNegativeOneAndString is a helper for runtime struct id
   449  func AppendNegativeOneAndStringAsBytes(b []byte, str []byte) []byte {
   450  	o := AppendInt64(b, -1)
   451  	return AppendStringFromBytes(o, str)
   452  }