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

     1  package msgp
     2  
     3  import (
     4  	"bufio"
     5  	"encoding/base64"
     6  	"encoding/json"
     7  	"io"
     8  	"strconv"
     9  	"time"
    10  )
    11  
    12  var unfuns [_maxtype]func(jsWriter, []byte, []byte) ([]byte, []byte, error)
    13  
    14  func init() {
    15  
    16  	// NOTE(pmh): this is best expressed as a jump table,
    17  	// but gc doesn't do that yet. revisit post-go1.5.
    18  	unfuns = [_maxtype]func(jsWriter, []byte, []byte) ([]byte, []byte, error){
    19  		StrType:        rwStringBytes,
    20  		BinType:        rwBytesBytes,
    21  		MapType:        rwMapBytes,
    22  		ArrayType:      rwArrayBytes,
    23  		Float64Type:    rwFloat64Bytes,
    24  		Float32Type:    rwFloat32Bytes,
    25  		BoolType:       rwBoolBytes,
    26  		IntType:        rwIntBytes,
    27  		UintType:       rwUintBytes,
    28  		NilType:        rwNullBytes,
    29  		ExtensionType:  rwExtensionBytes,
    30  		Complex64Type:  rwExtensionBytes,
    31  		Complex128Type: rwExtensionBytes,
    32  		TimeType:       rwTimeBytes,
    33  	}
    34  }
    35  
    36  // UnmarshalAsJSON takes raw messagepack and writes
    37  // it as JSON to 'w'. If an error is returned, the
    38  // bytes not translated will also be returned. If
    39  // no errors are encountered, the length of the returned
    40  // slice will be zero.
    41  func UnmarshalAsJSON(w io.Writer, msg []byte) ([]byte, error) {
    42  	var (
    43  		scratch []byte
    44  		cast    bool
    45  		dst     jsWriter
    46  		err     error
    47  	)
    48  	if jsw, ok := w.(jsWriter); ok {
    49  		dst = jsw
    50  		cast = true
    51  	} else {
    52  		dst = bufio.NewWriterSize(w, 512)
    53  	}
    54  	for len(msg) > 0 && err == nil {
    55  		msg, scratch, err = writeNext(dst, msg, scratch)
    56  	}
    57  	if !cast && err == nil {
    58  		err = dst.(*bufio.Writer).Flush()
    59  	}
    60  	return msg, err
    61  }
    62  
    63  func writeNext(w jsWriter, msg []byte, scratch []byte) ([]byte, []byte, error) {
    64  	if len(msg) < 1 {
    65  		return msg, scratch, ErrShortBytes
    66  	}
    67  	t := getType(msg[0])
    68  	if t == InvalidType {
    69  		return msg, scratch, InvalidPrefixError(msg[0])
    70  	}
    71  	if t == ExtensionType {
    72  		et, err := peekExtension(msg)
    73  		if err != nil {
    74  			return nil, scratch, err
    75  		}
    76  		if et == TimeExtension {
    77  			t = TimeType
    78  		}
    79  	}
    80  	return unfuns[t](w, msg, scratch)
    81  }
    82  
    83  func rwArrayBytes(w jsWriter, msg []byte, scratch []byte) ([]byte, []byte, error) {
    84  	var nbs *NilBitsStack
    85  	sz, msg, err := nbs.ReadArrayHeaderBytes(msg)
    86  	if err != nil {
    87  		return msg, scratch, err
    88  	}
    89  	err = w.WriteByte('[')
    90  	if err != nil {
    91  		return msg, scratch, err
    92  	}
    93  	for i := uint32(0); i < sz; i++ {
    94  		if i != 0 {
    95  			err = w.WriteByte(',')
    96  			if err != nil {
    97  				return msg, scratch, err
    98  			}
    99  		}
   100  		msg, scratch, err = writeNext(w, msg, scratch)
   101  		if err != nil {
   102  			return msg, scratch, err
   103  		}
   104  	}
   105  	err = w.WriteByte(']')
   106  	return msg, scratch, err
   107  }
   108  
   109  func rwMapBytes(w jsWriter, msg []byte, scratch []byte) ([]byte, []byte, error) {
   110  	var nbs *NilBitsStack
   111  	sz, msg, err := nbs.ReadMapHeaderBytes(msg)
   112  	if err != nil {
   113  		return msg, scratch, err
   114  	}
   115  	err = w.WriteByte('{')
   116  	if err != nil {
   117  		return msg, scratch, err
   118  	}
   119  	for i := uint32(0); i < sz; i++ {
   120  		if i != 0 {
   121  			err = w.WriteByte(',')
   122  			if err != nil {
   123  				return msg, scratch, err
   124  			}
   125  		}
   126  		msg, scratch, err = rwMapKeyBytes(w, msg, scratch)
   127  		if err != nil {
   128  			return msg, scratch, err
   129  		}
   130  		err = w.WriteByte(':')
   131  		if err != nil {
   132  			return msg, scratch, err
   133  		}
   134  		msg, scratch, err = writeNext(w, msg, scratch)
   135  		if err != nil {
   136  			return msg, scratch, err
   137  		}
   138  	}
   139  	err = w.WriteByte('}')
   140  	return msg, scratch, err
   141  }
   142  
   143  func rwMapKeyBytes(w jsWriter, msg []byte, scratch []byte) ([]byte, []byte, error) {
   144  	msg, scratch, err := rwStringBytes(w, msg, scratch)
   145  	if err != nil {
   146  		if tperr, ok := err.(TypeError); ok && tperr.Encoded == BinType {
   147  			return rwBytesBytes(w, msg, scratch)
   148  		}
   149  	}
   150  	return msg, scratch, err
   151  }
   152  
   153  func rwStringBytes(w jsWriter, msg []byte, scratch []byte) ([]byte, []byte, error) {
   154  	var nbs *NilBitsStack
   155  	str, msg, err := nbs.ReadStringZC(msg)
   156  	if err != nil {
   157  		return msg, scratch, err
   158  	}
   159  	_, err = rwquoted(w, str)
   160  	return msg, scratch, err
   161  }
   162  
   163  func rwBytesBytes(w jsWriter, msg []byte, scratch []byte) ([]byte, []byte, error) {
   164  	var nbs *NilBitsStack
   165  	bts, msg, err := nbs.ReadBytesZC(msg)
   166  	if err != nil {
   167  		return msg, scratch, err
   168  	}
   169  	l := base64.StdEncoding.EncodedLen(len(bts))
   170  	if cap(scratch) >= l {
   171  		scratch = scratch[0:l]
   172  	} else {
   173  		scratch = make([]byte, l)
   174  	}
   175  	base64.StdEncoding.Encode(scratch, bts)
   176  	err = w.WriteByte('"')
   177  	if err != nil {
   178  		return msg, scratch, err
   179  	}
   180  	_, err = w.Write(scratch)
   181  	if err != nil {
   182  		return msg, scratch, err
   183  	}
   184  	err = w.WriteByte('"')
   185  	return msg, scratch, err
   186  }
   187  
   188  func rwNullBytes(w jsWriter, msg []byte, scratch []byte) ([]byte, []byte, error) {
   189  	var nbs *NilBitsStack
   190  	msg, err := nbs.ReadNilBytes(msg)
   191  	if err != nil {
   192  		return msg, scratch, err
   193  	}
   194  	_, err = w.Write(null)
   195  	return msg, scratch, err
   196  }
   197  
   198  func rwBoolBytes(w jsWriter, msg []byte, scratch []byte) ([]byte, []byte, error) {
   199  	var nbs *NilBitsStack
   200  	b, msg, err := nbs.ReadBoolBytes(msg)
   201  	if err != nil {
   202  		return msg, scratch, err
   203  	}
   204  	if b {
   205  		_, err = w.WriteString("true")
   206  		return msg, scratch, err
   207  	}
   208  	_, err = w.WriteString("false")
   209  	return msg, scratch, err
   210  }
   211  
   212  func rwIntBytes(w jsWriter, msg []byte, scratch []byte) ([]byte, []byte, error) {
   213  	var nbs *NilBitsStack
   214  	i, msg, err := nbs.ReadInt64Bytes(msg)
   215  	if err != nil {
   216  		return msg, scratch, err
   217  	}
   218  	scratch = strconv.AppendInt(scratch[0:0], i, 10)
   219  	_, err = w.Write(scratch)
   220  	return msg, scratch, err
   221  }
   222  
   223  func rwUintBytes(w jsWriter, msg []byte, scratch []byte) ([]byte, []byte, error) {
   224  	var nbs *NilBitsStack
   225  	u, msg, err := nbs.ReadUint64Bytes(msg)
   226  	if err != nil {
   227  		return msg, scratch, err
   228  	}
   229  	scratch = strconv.AppendUint(scratch[0:0], u, 10)
   230  	_, err = w.Write(scratch)
   231  	return msg, scratch, err
   232  }
   233  
   234  func rwFloatBytes(w jsWriter, msg []byte, f64 bool, scratch []byte) ([]byte, []byte, error) {
   235  	var nbs *NilBitsStack
   236  	var f float64
   237  	var err error
   238  	var sz int
   239  	if f64 {
   240  		sz = 64
   241  		f, msg, err = nbs.ReadFloat64Bytes(msg)
   242  	} else {
   243  		sz = 32
   244  		var v float32
   245  		v, msg, err = nbs.ReadFloat32Bytes(msg)
   246  		f = float64(v)
   247  	}
   248  	if err != nil {
   249  		return msg, scratch, err
   250  	}
   251  	scratch = strconv.AppendFloat(scratch, f, 'f', -1, sz)
   252  	_, err = w.Write(scratch)
   253  	return msg, scratch, err
   254  }
   255  
   256  func rwFloat32Bytes(w jsWriter, msg []byte, scratch []byte) ([]byte, []byte, error) {
   257  	var nbs *NilBitsStack
   258  	var f float32
   259  	var err error
   260  	f, msg, err = nbs.ReadFloat32Bytes(msg)
   261  	if err != nil {
   262  		return msg, scratch, err
   263  	}
   264  	scratch = strconv.AppendFloat(scratch[:0], float64(f), 'f', -1, 32)
   265  	_, err = w.Write(scratch)
   266  	return msg, scratch, err
   267  }
   268  
   269  func rwFloat64Bytes(w jsWriter, msg []byte, scratch []byte) ([]byte, []byte, error) {
   270  	var nbs *NilBitsStack
   271  	var f float64
   272  	var err error
   273  	f, msg, err = nbs.ReadFloat64Bytes(msg)
   274  	if err != nil {
   275  		return msg, scratch, err
   276  	}
   277  	scratch = strconv.AppendFloat(scratch[:0], f, 'f', -1, 64)
   278  	_, err = w.Write(scratch)
   279  	return msg, scratch, err
   280  }
   281  
   282  func rwTimeBytes(w jsWriter, msg []byte, scratch []byte) ([]byte, []byte, error) {
   283  	var nbs *NilBitsStack
   284  	var t time.Time
   285  	var err error
   286  	t, msg, err = nbs.ReadTimeBytes(msg)
   287  	if err != nil {
   288  		return msg, scratch, err
   289  	}
   290  	bts, err := t.MarshalJSON()
   291  	if err != nil {
   292  		return msg, scratch, err
   293  	}
   294  	_, err = w.Write(bts)
   295  	return msg, scratch, err
   296  }
   297  
   298  func rwExtensionBytes(w jsWriter, msg []byte, scratch []byte) ([]byte, []byte, error) {
   299  	var nbs *NilBitsStack
   300  	var err error
   301  	var et int8
   302  	et, err = peekExtension(msg)
   303  	if err != nil {
   304  		return msg, scratch, err
   305  	}
   306  
   307  	// if it's time.Time
   308  	if et == TimeExtension {
   309  		var tm time.Time
   310  		tm, msg, err = nbs.ReadTimeBytes(msg)
   311  		if err != nil {
   312  			return msg, scratch, err
   313  		}
   314  		bts, err := tm.MarshalJSON()
   315  		if err != nil {
   316  			return msg, scratch, err
   317  		}
   318  		_, err = w.Write(bts)
   319  		return msg, scratch, err
   320  	}
   321  
   322  	// if the extension is registered,
   323  	// use its canonical JSON form
   324  	if f, ok := extensionReg[et]; ok {
   325  		e := f()
   326  		msg, err = nbs.ReadExtensionBytes(msg, e)
   327  		if err != nil {
   328  			return msg, scratch, err
   329  		}
   330  		bts, err := json.Marshal(e)
   331  		if err != nil {
   332  			return msg, scratch, err
   333  		}
   334  		_, err = w.Write(bts)
   335  		return msg, scratch, err
   336  	}
   337  
   338  	// otherwise, write `{"type": <num>, "data": "<base64data>"}`
   339  	r := RawExtension{}
   340  	r.Type = et
   341  	msg, err = nbs.ReadExtensionBytes(msg, &r)
   342  	if err != nil {
   343  		return msg, scratch, err
   344  	}
   345  	scratch, err = writeExt(w, r, scratch)
   346  	return msg, scratch, err
   347  }
   348  
   349  func writeExt(w jsWriter, r RawExtension, scratch []byte) ([]byte, error) {
   350  	_, err := w.WriteString(`{"type":`)
   351  	if err != nil {
   352  		return scratch, err
   353  	}
   354  	scratch = strconv.AppendInt(scratch[0:0], int64(r.Type), 10)
   355  	_, err = w.Write(scratch)
   356  	if err != nil {
   357  		return scratch, err
   358  	}
   359  	_, err = w.WriteString(`,"data":"`)
   360  	if err != nil {
   361  		return scratch, err
   362  	}
   363  	l := base64.StdEncoding.EncodedLen(len(r.Data))
   364  	if cap(scratch) >= l {
   365  		scratch = scratch[0:l]
   366  	} else {
   367  		scratch = make([]byte, l)
   368  	}
   369  	base64.StdEncoding.Encode(scratch, r.Data)
   370  	_, err = w.Write(scratch)
   371  	if err != nil {
   372  		return scratch, err
   373  	}
   374  	_, err = w.WriteString(`"}`)
   375  	return scratch, err
   376  }