github.com/lheiskan/zebrapack@v4.1.1-0.20181107023619-e955d028f9bf+incompatible/msgp/json.go (about)

     1  package msgp
     2  
     3  import (
     4  	"bufio"
     5  	"encoding/base64"
     6  	"encoding/json"
     7  	"io"
     8  	"strconv"
     9  	"unicode/utf8"
    10  )
    11  
    12  var (
    13  	null = []byte("null")
    14  	hex  = []byte("0123456789abcdef")
    15  )
    16  
    17  var defuns [_maxtype]func(jsWriter, *Reader) (int, error)
    18  
    19  // note: there is an initialization loop if
    20  // this isn't set up during init()
    21  func init() {
    22  	// since none of these functions are inline-able,
    23  	// there is not much of a penalty to the indirect
    24  	// call. however, this is best expressed as a jump-table...
    25  	defuns = [_maxtype]func(jsWriter, *Reader) (int, error){
    26  		StrType:        rwString,
    27  		BinType:        rwBytes,
    28  		MapType:        rwMap,
    29  		ArrayType:      rwArray,
    30  		Float64Type:    rwFloat64,
    31  		Float32Type:    rwFloat32,
    32  		BoolType:       rwBool,
    33  		IntType:        rwInt,
    34  		UintType:       rwUint,
    35  		NilType:        rwNil,
    36  		ExtensionType:  rwExtension,
    37  		Complex64Type:  rwExtension,
    38  		Complex128Type: rwExtension,
    39  		TimeType:       rwTime,
    40  	}
    41  }
    42  
    43  // this is the interface
    44  // used to write json
    45  type jsWriter interface {
    46  	io.Writer
    47  	io.ByteWriter
    48  	WriteString(string) (int, error)
    49  }
    50  
    51  // CopyToJSON reads MessagePack from 'src' and copies it
    52  // as JSON to 'dst' until EOF.
    53  func CopyToJSON(dst io.Writer, src io.Reader) (n int64, err error) {
    54  	r := NewReader(src)
    55  	n, err = r.WriteToJSON(dst)
    56  	freeR(r)
    57  	return
    58  }
    59  
    60  // WriteToJSON translates MessagePack from 'r' and writes it as
    61  // JSON to 'w' until the underlying reader returns io.EOF. It returns
    62  // the number of bytes written, and an error if it stopped before EOF.
    63  func (r *Reader) WriteToJSON(w io.Writer) (n int64, err error) {
    64  	var j jsWriter
    65  	var bf *bufio.Writer
    66  	if jsw, ok := w.(jsWriter); ok {
    67  		j = jsw
    68  	} else {
    69  		bf = bufio.NewWriter(w)
    70  		j = bf
    71  	}
    72  	var nn int
    73  	for err == nil {
    74  		nn, err = rwNext(j, r)
    75  		n += int64(nn)
    76  	}
    77  	if err != io.EOF {
    78  		if bf != nil {
    79  			bf.Flush()
    80  		}
    81  		return
    82  	}
    83  	err = nil
    84  	if bf != nil {
    85  		err = bf.Flush()
    86  	}
    87  	return
    88  }
    89  
    90  func rwNext(w jsWriter, src *Reader) (int, error) {
    91  	t, err := src.NextType()
    92  	if err != nil {
    93  		return 0, err
    94  	}
    95  	return defuns[t](w, src)
    96  }
    97  
    98  func rwMap(dst jsWriter, src *Reader) (n int, err error) {
    99  	var comma bool
   100  	var sz uint32
   101  	var field []byte
   102  
   103  	sz, err = src.ReadMapHeader()
   104  	if err != nil {
   105  		return
   106  	}
   107  
   108  	if sz == 0 {
   109  		return dst.WriteString("{}")
   110  	}
   111  
   112  	err = dst.WriteByte('{')
   113  	if err != nil {
   114  		return
   115  	}
   116  	n++
   117  	var nn int
   118  	for i := uint32(0); i < sz; i++ {
   119  		if comma {
   120  			err = dst.WriteByte(',')
   121  			if err != nil {
   122  				return
   123  			}
   124  			n++
   125  		}
   126  
   127  		field, err = src.ReadMapKeyPtr()
   128  		if err != nil {
   129  			return
   130  		}
   131  		nn, err = rwquoted(dst, field)
   132  		n += nn
   133  		if err != nil {
   134  			return
   135  		}
   136  
   137  		err = dst.WriteByte(':')
   138  		if err != nil {
   139  			return
   140  		}
   141  		n++
   142  		nn, err = rwNext(dst, src)
   143  		n += nn
   144  		if err != nil {
   145  			return
   146  		}
   147  		if !comma {
   148  			comma = true
   149  		}
   150  	}
   151  
   152  	err = dst.WriteByte('}')
   153  	if err != nil {
   154  		return
   155  	}
   156  	n++
   157  	return
   158  }
   159  
   160  func rwArray(dst jsWriter, src *Reader) (n int, err error) {
   161  	err = dst.WriteByte('[')
   162  	if err != nil {
   163  		return
   164  	}
   165  	var sz uint32
   166  	var nn int
   167  	sz, err = src.ReadArrayHeader()
   168  	if err != nil {
   169  		return
   170  	}
   171  	comma := false
   172  	for i := uint32(0); i < sz; i++ {
   173  		if comma {
   174  			err = dst.WriteByte(',')
   175  			if err != nil {
   176  				return
   177  			}
   178  			n++
   179  		}
   180  		nn, err = rwNext(dst, src)
   181  		n += nn
   182  		if err != nil {
   183  			return
   184  		}
   185  		comma = true
   186  	}
   187  
   188  	err = dst.WriteByte(']')
   189  	if err != nil {
   190  		return
   191  	}
   192  	n++
   193  	return
   194  }
   195  
   196  func rwNil(dst jsWriter, src *Reader) (int, error) {
   197  	err := src.ReadNil()
   198  	if err != nil {
   199  		return 0, err
   200  	}
   201  	return dst.Write(null)
   202  }
   203  
   204  func rwFloat32(dst jsWriter, src *Reader) (int, error) {
   205  	f, err := src.ReadFloat32()
   206  	if err != nil {
   207  		return 0, err
   208  	}
   209  	src.scratch = strconv.AppendFloat(src.scratch[:0], float64(f), 'f', -1, 64)
   210  	return dst.Write(src.scratch)
   211  }
   212  
   213  func rwFloat64(dst jsWriter, src *Reader) (int, error) {
   214  	f, err := src.ReadFloat64()
   215  	if err != nil {
   216  		return 0, err
   217  	}
   218  	src.scratch = strconv.AppendFloat(src.scratch[:0], f, 'f', -1, 32)
   219  	return dst.Write(src.scratch)
   220  }
   221  
   222  func rwInt(dst jsWriter, src *Reader) (int, error) {
   223  	i, err := src.ReadInt64()
   224  	if err != nil {
   225  		return 0, err
   226  	}
   227  	src.scratch = strconv.AppendInt(src.scratch[:0], i, 10)
   228  	return dst.Write(src.scratch)
   229  }
   230  
   231  func rwUint(dst jsWriter, src *Reader) (int, error) {
   232  	u, err := src.ReadUint64()
   233  	if err != nil {
   234  		return 0, err
   235  	}
   236  	src.scratch = strconv.AppendUint(src.scratch[:0], u, 10)
   237  	return dst.Write(src.scratch)
   238  }
   239  
   240  func rwBool(dst jsWriter, src *Reader) (int, error) {
   241  	b, err := src.ReadBool()
   242  	if err != nil {
   243  		return 0, err
   244  	}
   245  	if b {
   246  		return dst.WriteString("true")
   247  	}
   248  	return dst.WriteString("false")
   249  }
   250  
   251  func rwTime(dst jsWriter, src *Reader) (int, error) {
   252  	t, err := src.ReadTime()
   253  	if err != nil {
   254  		return 0, err
   255  	}
   256  	bts, err := t.MarshalJSON()
   257  	if err != nil {
   258  		return 0, err
   259  	}
   260  	return dst.Write(bts)
   261  }
   262  
   263  func rwExtension(dst jsWriter, src *Reader) (n int, err error) {
   264  	et, err := src.peekExtensionType()
   265  	if err != nil {
   266  		return 0, err
   267  	}
   268  
   269  	// registered extensions can override
   270  	// the JSON encoding
   271  	if j, ok := extensionReg[et]; ok {
   272  		var bts []byte
   273  		e := j()
   274  		err = src.ReadExtension(e)
   275  		if err != nil {
   276  			return
   277  		}
   278  		bts, err = json.Marshal(e)
   279  		if err != nil {
   280  			return
   281  		}
   282  		return dst.Write(bts)
   283  	}
   284  
   285  	e := RawExtension{}
   286  	e.Type = et
   287  	err = src.ReadExtension(&e)
   288  	if err != nil {
   289  		return
   290  	}
   291  
   292  	var nn int
   293  	err = dst.WriteByte('{')
   294  	if err != nil {
   295  		return
   296  	}
   297  	n++
   298  
   299  	nn, err = dst.WriteString(`"type:"`)
   300  	n += nn
   301  	if err != nil {
   302  		return
   303  	}
   304  
   305  	src.scratch = strconv.AppendInt(src.scratch[0:0], int64(e.Type), 10)
   306  	nn, err = dst.Write(src.scratch)
   307  	n += nn
   308  	if err != nil {
   309  		return
   310  	}
   311  
   312  	nn, err = dst.WriteString(`,"data":"`)
   313  	n += nn
   314  	if err != nil {
   315  		return
   316  	}
   317  
   318  	enc := base64.NewEncoder(base64.StdEncoding, dst)
   319  
   320  	nn, err = enc.Write(e.Data)
   321  	n += nn
   322  	if err != nil {
   323  		return
   324  	}
   325  	err = enc.Close()
   326  	if err != nil {
   327  		return
   328  	}
   329  	nn, err = dst.WriteString(`"}`)
   330  	n += nn
   331  	return
   332  }
   333  
   334  func rwString(dst jsWriter, src *Reader) (n int, err error) {
   335  	var p []byte
   336  	p, err = src.R.Peek(1)
   337  	if err != nil {
   338  		return
   339  	}
   340  	lead := p[0]
   341  	var read int
   342  
   343  	if isfixstr(lead) {
   344  		read = int(rfixstr(lead))
   345  		src.R.Skip(1)
   346  		goto write
   347  	}
   348  
   349  	switch lead {
   350  	case mstr8:
   351  		p, err = src.R.Next(2)
   352  		if err != nil {
   353  			return
   354  		}
   355  		read = int(uint8(p[1]))
   356  	case mstr16:
   357  		p, err = src.R.Next(3)
   358  		if err != nil {
   359  			return
   360  		}
   361  		read = int(big.Uint16(p[1:]))
   362  	case mstr32:
   363  		p, err = src.R.Next(5)
   364  		if err != nil {
   365  			return
   366  		}
   367  		read = int(big.Uint32(p[1:]))
   368  	default:
   369  		err = badPrefix(StrType, lead)
   370  		return
   371  	}
   372  write:
   373  	p, err = src.R.Next(read)
   374  	if err != nil {
   375  		return
   376  	}
   377  	n, err = rwquoted(dst, p)
   378  	return
   379  }
   380  
   381  func rwBytes(dst jsWriter, src *Reader) (n int, err error) {
   382  	var nn int
   383  	err = dst.WriteByte('"')
   384  	if err != nil {
   385  		return
   386  	}
   387  	n++
   388  	src.scratch, err = src.ReadBytes(src.scratch[:0])
   389  	if err != nil {
   390  		return
   391  	}
   392  	enc := base64.NewEncoder(base64.StdEncoding, dst)
   393  	nn, err = enc.Write(src.scratch)
   394  	n += nn
   395  	if err != nil {
   396  		return
   397  	}
   398  	err = enc.Close()
   399  	if err != nil {
   400  		return
   401  	}
   402  	err = dst.WriteByte('"')
   403  	if err != nil {
   404  		return
   405  	}
   406  	n++
   407  	return
   408  }
   409  
   410  // Below (c) The Go Authors, 2009-2014
   411  // Subject to the BSD-style license found at http://golang.org
   412  //
   413  // see: encoding/json/encode.go:(*encodeState).stringbytes()
   414  func rwquoted(dst jsWriter, s []byte) (n int, err error) {
   415  	var nn int
   416  	err = dst.WriteByte('"')
   417  	if err != nil {
   418  		return
   419  	}
   420  	n++
   421  	start := 0
   422  	for i := 0; i < len(s); {
   423  		if b := s[i]; b < utf8.RuneSelf {
   424  			if 0x20 <= b && b != '\\' && b != '"' && b != '<' && b != '>' && b != '&' {
   425  				i++
   426  				continue
   427  			}
   428  			if start < i {
   429  				nn, err = dst.Write(s[start:i])
   430  				n += nn
   431  				if err != nil {
   432  					return
   433  				}
   434  			}
   435  			switch b {
   436  			case '\\', '"':
   437  				err = dst.WriteByte('\\')
   438  				if err != nil {
   439  					return
   440  				}
   441  				n++
   442  				err = dst.WriteByte(b)
   443  				if err != nil {
   444  					return
   445  				}
   446  				n++
   447  			case '\n':
   448  				err = dst.WriteByte('\\')
   449  				if err != nil {
   450  					return
   451  				}
   452  				n++
   453  				err = dst.WriteByte('n')
   454  				if err != nil {
   455  					return
   456  				}
   457  				n++
   458  			case '\r':
   459  				err = dst.WriteByte('\\')
   460  				if err != nil {
   461  					return
   462  				}
   463  				n++
   464  				err = dst.WriteByte('r')
   465  				if err != nil {
   466  					return
   467  				}
   468  				n++
   469  			default:
   470  				nn, err = dst.WriteString(`\u00`)
   471  				n += nn
   472  				if err != nil {
   473  					return
   474  				}
   475  				err = dst.WriteByte(hex[b>>4])
   476  				if err != nil {
   477  					return
   478  				}
   479  				n++
   480  				err = dst.WriteByte(hex[b&0xF])
   481  				if err != nil {
   482  					return
   483  				}
   484  				n++
   485  			}
   486  			i++
   487  			start = i
   488  			continue
   489  		}
   490  		c, size := utf8.DecodeRune(s[i:])
   491  		if c == utf8.RuneError && size == 1 {
   492  			if start < i {
   493  				nn, err = dst.Write(s[start:i])
   494  				n += nn
   495  				if err != nil {
   496  					return
   497  				}
   498  				nn, err = dst.WriteString(`\ufffd`)
   499  				n += nn
   500  				if err != nil {
   501  					return
   502  				}
   503  				i += size
   504  				start = i
   505  				continue
   506  			}
   507  		}
   508  		if c == '\u2028' || c == '\u2029' {
   509  			if start < i {
   510  				nn, err = dst.Write(s[start:i])
   511  				n += nn
   512  				if err != nil {
   513  					return
   514  				}
   515  				nn, err = dst.WriteString(`\u202`)
   516  				n += nn
   517  				if err != nil {
   518  					return
   519  				}
   520  				err = dst.WriteByte(hex[c&0xF])
   521  				if err != nil {
   522  					return
   523  				}
   524  				n++
   525  			}
   526  		}
   527  		i += size
   528  	}
   529  	if start < len(s) {
   530  		nn, err = dst.Write(s[start:])
   531  		n += nn
   532  		if err != nil {
   533  			return
   534  		}
   535  	}
   536  	err = dst.WriteByte('"')
   537  	if err != nil {
   538  		return
   539  	}
   540  	n++
   541  	return
   542  }