mirror of
				https://github.com/superseriousbusiness/gotosocial.git
				synced 2025-10-31 14:42:26 -05:00 
			
		
		
		
	* update all but bun libraries Signed-off-by: kim <grufwub@gmail.com> * remove my personal build script changes Signed-off-by: kim <grufwub@gmail.com>
		
			
				
	
	
		
			818 lines
		
	
	
	
		
			16 KiB
		
	
	
	
		
			Go
		
	
	
	
	
	
			
		
		
	
	
			818 lines
		
	
	
	
		
			16 KiB
		
	
	
	
		
			Go
		
	
	
	
	
	
| // Copyright (c) 2012-2020 Ugorji Nwoke. All rights reserved.
 | |
| // Use of this source code is governed by a MIT license found in the LICENSE file.
 | |
| 
 | |
| package codec
 | |
| 
 | |
| import "io"
 | |
| 
 | |
| // decReader abstracts the reading source, allowing implementations that can
 | |
| // read from an io.Reader or directly off a byte slice with zero-copying.
 | |
| type decReader interface {
 | |
| 	// readx will return a view of the []byte if decoding from a []byte, OR
 | |
| 	// read into the implementation scratch buffer if possible i.e. n < len(scratchbuf), OR
 | |
| 	// create a new []byte and read into that
 | |
| 	readx(n uint) []byte
 | |
| 
 | |
| 	readb([]byte)
 | |
| 
 | |
| 	readn1() byte
 | |
| 	readn2() [2]byte
 | |
| 	// readn3 will read 3 bytes into the top-most elements of a 4-byte array
 | |
| 	readn3() [4]byte
 | |
| 	readn4() [4]byte
 | |
| 	readn8() [8]byte
 | |
| 	// readn1eof() (v uint8, eof bool)
 | |
| 
 | |
| 	// // read up to 8 bytes at a time
 | |
| 	// readn(num uint8) (v [8]byte)
 | |
| 
 | |
| 	numread() uint // number of bytes read
 | |
| 
 | |
| 	// skip any whitespace characters, and return the first non-matching byte
 | |
| 	skipWhitespace() (token byte)
 | |
| 
 | |
| 	// jsonReadNum will include last read byte in first element of slice,
 | |
| 	// and continue numeric characters until it sees a non-numeric char
 | |
| 	// or EOF. If it sees a non-numeric character, it will unread that.
 | |
| 	jsonReadNum() []byte
 | |
| 
 | |
| 	// jsonReadAsisChars will read json plain characters (anything but " or \)
 | |
| 	// and return a slice terminated by a non-json asis character.
 | |
| 	jsonReadAsisChars() []byte
 | |
| 
 | |
| 	// skip will skip any byte that matches, and return the first non-matching byte
 | |
| 	// skip(accept *bitset256) (token byte)
 | |
| 
 | |
| 	// readTo will read any byte that matches, stopping once no-longer matching.
 | |
| 	// readTo(accept *bitset256) (out []byte)
 | |
| 
 | |
| 	// readUntil will read, only stopping once it matches the 'stop' byte (which it excludes).
 | |
| 	readUntil(stop byte) (out []byte)
 | |
| }
 | |
| 
 | |
| // ------------------------------------------------
 | |
| 
 | |
| type unreadByteStatus uint8
 | |
| 
 | |
| // unreadByteStatus goes from
 | |
| // undefined (when initialized) -- (read) --> canUnread -- (unread) --> canRead ...
 | |
| const (
 | |
| 	unreadByteUndefined unreadByteStatus = iota
 | |
| 	unreadByteCanRead
 | |
| 	unreadByteCanUnread
 | |
| )
 | |
| 
 | |
| // --------------------
 | |
| 
 | |
| type ioDecReaderCommon struct {
 | |
| 	r io.Reader // the reader passed in
 | |
| 
 | |
| 	n uint // num read
 | |
| 
 | |
| 	l  byte             // last byte
 | |
| 	ls unreadByteStatus // last byte status
 | |
| 
 | |
| 	b [6]byte // tiny buffer for reading single bytes
 | |
| 
 | |
| 	blist *bytesFreelist
 | |
| 
 | |
| 	bufr []byte // buffer for readTo/readUntil
 | |
| }
 | |
| 
 | |
| func (z *ioDecReaderCommon) reset(r io.Reader, blist *bytesFreelist) {
 | |
| 	z.blist = blist
 | |
| 	z.r = r
 | |
| 	z.ls = unreadByteUndefined
 | |
| 	z.l, z.n = 0, 0
 | |
| 	z.bufr = z.blist.check(z.bufr, 256)
 | |
| }
 | |
| 
 | |
| func (z *ioDecReaderCommon) numread() uint {
 | |
| 	return z.n
 | |
| }
 | |
| 
 | |
| // ------------------------------------------
 | |
| 
 | |
| // ioDecReader is a decReader that reads off an io.Reader.
 | |
| //
 | |
| // It also has a fallback implementation of ByteScanner if needed.
 | |
| type ioDecReader struct {
 | |
| 	ioDecReaderCommon
 | |
| 
 | |
| 	br io.ByteScanner
 | |
| 
 | |
| 	x [64 + 48]byte // for: get struct field name, swallow valueTypeBytes, etc
 | |
| }
 | |
| 
 | |
| func (z *ioDecReader) reset(r io.Reader, blist *bytesFreelist) {
 | |
| 	z.ioDecReaderCommon.reset(r, blist)
 | |
| 
 | |
| 	z.br, _ = r.(io.ByteScanner)
 | |
| }
 | |
| 
 | |
| func (z *ioDecReader) Read(p []byte) (n int, err error) {
 | |
| 	if len(p) == 0 {
 | |
| 		return
 | |
| 	}
 | |
| 	var firstByte bool
 | |
| 	if z.ls == unreadByteCanRead {
 | |
| 		z.ls = unreadByteCanUnread
 | |
| 		p[0] = z.l
 | |
| 		if len(p) == 1 {
 | |
| 			n = 1
 | |
| 			return
 | |
| 		}
 | |
| 		firstByte = true
 | |
| 		p = p[1:]
 | |
| 	}
 | |
| 	n, err = z.r.Read(p)
 | |
| 	if n > 0 {
 | |
| 		if err == io.EOF && n == len(p) {
 | |
| 			err = nil // read was successful, so postpone EOF (till next time)
 | |
| 		}
 | |
| 		z.l = p[n-1]
 | |
| 		z.ls = unreadByteCanUnread
 | |
| 	}
 | |
| 	if firstByte {
 | |
| 		n++
 | |
| 	}
 | |
| 	return
 | |
| }
 | |
| 
 | |
| func (z *ioDecReader) ReadByte() (c byte, err error) {
 | |
| 	if z.br != nil {
 | |
| 		c, err = z.br.ReadByte()
 | |
| 		if err == nil {
 | |
| 			z.l = c
 | |
| 			z.ls = unreadByteCanUnread
 | |
| 		}
 | |
| 		return
 | |
| 	}
 | |
| 
 | |
| 	n, err := z.Read(z.b[:1])
 | |
| 	if n == 1 {
 | |
| 		c = z.b[0]
 | |
| 		if err == io.EOF {
 | |
| 			err = nil // read was successful, so postpone EOF (till next time)
 | |
| 		}
 | |
| 	}
 | |
| 	return
 | |
| }
 | |
| 
 | |
| func (z *ioDecReader) UnreadByte() (err error) {
 | |
| 	if z.br != nil {
 | |
| 		err = z.br.UnreadByte()
 | |
| 		if err == nil {
 | |
| 			z.ls = unreadByteCanRead
 | |
| 		}
 | |
| 		return
 | |
| 	}
 | |
| 
 | |
| 	switch z.ls {
 | |
| 	case unreadByteCanUnread:
 | |
| 		z.ls = unreadByteCanRead
 | |
| 	case unreadByteCanRead:
 | |
| 		err = errDecUnreadByteLastByteNotRead
 | |
| 	case unreadByteUndefined:
 | |
| 		err = errDecUnreadByteNothingToRead
 | |
| 	default:
 | |
| 		err = errDecUnreadByteUnknown
 | |
| 	}
 | |
| 	return
 | |
| }
 | |
| 
 | |
| func (z *ioDecReader) readn2() (bs [2]byte) {
 | |
| 	z.readb(bs[:])
 | |
| 	return
 | |
| }
 | |
| 
 | |
| func (z *ioDecReader) readn3() (bs [4]byte) {
 | |
| 	z.readb(bs[1:])
 | |
| 	return
 | |
| }
 | |
| 
 | |
| func (z *ioDecReader) readn4() (bs [4]byte) {
 | |
| 	z.readb(bs[:])
 | |
| 	return
 | |
| }
 | |
| 
 | |
| func (z *ioDecReader) readn8() (bs [8]byte) {
 | |
| 	z.readb(bs[:])
 | |
| 	return
 | |
| }
 | |
| 
 | |
| func (z *ioDecReader) readx(n uint) (bs []byte) {
 | |
| 	if n == 0 {
 | |
| 		return
 | |
| 	}
 | |
| 	if n < uint(len(z.x)) {
 | |
| 		bs = z.x[:n]
 | |
| 	} else {
 | |
| 		bs = make([]byte, n)
 | |
| 	}
 | |
| 	_, err := readFull(z.r, bs)
 | |
| 	halt.onerror(err)
 | |
| 	z.n += uint(len(bs))
 | |
| 	return
 | |
| }
 | |
| 
 | |
| func (z *ioDecReader) readb(bs []byte) {
 | |
| 	if len(bs) == 0 {
 | |
| 		return
 | |
| 	}
 | |
| 	_, err := readFull(z.r, bs)
 | |
| 	halt.onerror(err)
 | |
| 	z.n += uint(len(bs))
 | |
| }
 | |
| 
 | |
| func (z *ioDecReader) readn1() (b uint8) {
 | |
| 	b, err := z.ReadByte()
 | |
| 	halt.onerror(err)
 | |
| 	z.n++
 | |
| 	return
 | |
| }
 | |
| 
 | |
| func (z *ioDecReader) readn1eof() (b uint8, eof bool) {
 | |
| 	b, err := z.ReadByte()
 | |
| 	if err == nil {
 | |
| 		z.n++
 | |
| 	} else if err == io.EOF {
 | |
| 		eof = true
 | |
| 	} else {
 | |
| 		halt.onerror(err)
 | |
| 	}
 | |
| 	return
 | |
| }
 | |
| 
 | |
| func (z *ioDecReader) jsonReadNum() (bs []byte) {
 | |
| 	z.unreadn1()
 | |
| 	z.bufr = z.bufr[:0]
 | |
| LOOP:
 | |
| 	i, eof := z.readn1eof()
 | |
| 	if eof {
 | |
| 		return z.bufr
 | |
| 	}
 | |
| 	if isNumberChar(i) {
 | |
| 		z.bufr = append(z.bufr, i)
 | |
| 		goto LOOP
 | |
| 	}
 | |
| 	z.unreadn1()
 | |
| 	return z.bufr
 | |
| }
 | |
| 
 | |
| func (z *ioDecReader) jsonReadAsisChars() (bs []byte) {
 | |
| 	z.bufr = z.bufr[:0]
 | |
| LOOP:
 | |
| 	i := z.readn1()
 | |
| 	z.bufr = append(z.bufr, i)
 | |
| 	if i == '"' || i == '\\' {
 | |
| 		return z.bufr
 | |
| 	}
 | |
| 	goto LOOP
 | |
| }
 | |
| 
 | |
| func (z *ioDecReader) skipWhitespace() (token byte) {
 | |
| LOOP:
 | |
| 	token = z.readn1()
 | |
| 	if isWhitespaceChar(token) {
 | |
| 		goto LOOP
 | |
| 	}
 | |
| 	return
 | |
| }
 | |
| 
 | |
| func (z *ioDecReader) readUntil(stop byte) []byte {
 | |
| 	z.bufr = z.bufr[:0]
 | |
| LOOP:
 | |
| 	token := z.readn1()
 | |
| 	z.bufr = append(z.bufr, token)
 | |
| 	if token == stop {
 | |
| 		return z.bufr[:len(z.bufr)-1]
 | |
| 	}
 | |
| 	goto LOOP
 | |
| }
 | |
| 
 | |
| func (z *ioDecReader) unreadn1() {
 | |
| 	err := z.UnreadByte()
 | |
| 	halt.onerror(err)
 | |
| 	z.n--
 | |
| }
 | |
| 
 | |
| // ------------------------------------
 | |
| 
 | |
| type bufioDecReader struct {
 | |
| 	ioDecReaderCommon
 | |
| 
 | |
| 	c   uint // cursor
 | |
| 	buf []byte
 | |
| }
 | |
| 
 | |
| func (z *bufioDecReader) reset(r io.Reader, bufsize int, blist *bytesFreelist) {
 | |
| 	z.ioDecReaderCommon.reset(r, blist)
 | |
| 	z.c = 0
 | |
| 	if cap(z.buf) < bufsize {
 | |
| 		z.buf = blist.get(bufsize)
 | |
| 	} else {
 | |
| 		z.buf = z.buf[:0]
 | |
| 	}
 | |
| }
 | |
| 
 | |
| func (z *bufioDecReader) readb(p []byte) {
 | |
| 	var n = uint(copy(p, z.buf[z.c:]))
 | |
| 	z.n += n
 | |
| 	z.c += n
 | |
| 	if len(p) != int(n) {
 | |
| 		z.readbFill(p, n, true, false)
 | |
| 	}
 | |
| }
 | |
| 
 | |
| func readbFillHandleErr(err error, must, eof bool) (isEOF bool) {
 | |
| 	if err == io.EOF {
 | |
| 		isEOF = true
 | |
| 	}
 | |
| 	if must && !(eof && isEOF) {
 | |
| 		halt.onerror(err)
 | |
| 	}
 | |
| 	return
 | |
| }
 | |
| 
 | |
| func (z *bufioDecReader) readbFill(p0 []byte, n uint, must, eof bool) (isEOF bool, err error) {
 | |
| 	// at this point, there's nothing in z.buf to read (z.buf is fully consumed)
 | |
| 	var p []byte
 | |
| 	if p0 != nil {
 | |
| 		p = p0[n:]
 | |
| 	}
 | |
| 	var n2 uint
 | |
| 	if len(p) > cap(z.buf) {
 | |
| 		n2, err = readFull(z.r, p)
 | |
| 		if err != nil {
 | |
| 			isEOF = readbFillHandleErr(err, must, eof)
 | |
| 			return
 | |
| 		}
 | |
| 		n += n2
 | |
| 		z.n += n2
 | |
| 		// always keep last byte in z.buf
 | |
| 		z.buf = z.buf[:1]
 | |
| 		z.buf[0] = p[len(p)-1]
 | |
| 		z.c = 1
 | |
| 		return
 | |
| 	}
 | |
| 	// z.c is now 0, and len(p) <= cap(z.buf)
 | |
| 	var n1 int
 | |
| LOOP:
 | |
| 	// for len(p) > 0 && z.err == nil {
 | |
| 	z.buf = z.buf[0:cap(z.buf)]
 | |
| 	n1, err = z.r.Read(z.buf)
 | |
| 	n2 = uint(n1)
 | |
| 	if n2 == 0 && err != nil {
 | |
| 		isEOF = readbFillHandleErr(err, must, eof)
 | |
| 		return
 | |
| 	}
 | |
| 	err = nil
 | |
| 	z.buf = z.buf[:n2]
 | |
| 	z.c = 0
 | |
| 	if len(p) > 0 {
 | |
| 		n2 = uint(copy(p, z.buf))
 | |
| 		z.c = n2
 | |
| 		n += n2
 | |
| 		z.n += n2
 | |
| 		p = p[n2:]
 | |
| 		if len(p) > 0 {
 | |
| 			goto LOOP
 | |
| 		}
 | |
| 		if z.c == 0 {
 | |
| 			z.buf = z.buf[:1]
 | |
| 			z.buf[0] = p[len(p)-1]
 | |
| 			z.c = 1
 | |
| 		}
 | |
| 	}
 | |
| 	return
 | |
| }
 | |
| 
 | |
| func (z *bufioDecReader) readn1() (b byte) {
 | |
| 	if z.c >= uint(len(z.buf)) {
 | |
| 		z.readbFill(nil, 0, true, false)
 | |
| 	}
 | |
| 	b = z.buf[z.c]
 | |
| 	z.c++
 | |
| 	z.n++
 | |
| 	return
 | |
| }
 | |
| 
 | |
| func (z *bufioDecReader) readn1eof() (b byte, eof bool) {
 | |
| 	if z.c >= uint(len(z.buf)) {
 | |
| 		eof, _ = z.readbFill(nil, 0, true, true)
 | |
| 		if eof {
 | |
| 			return
 | |
| 		}
 | |
| 	}
 | |
| 	b = z.buf[z.c]
 | |
| 	z.c++
 | |
| 	z.n++
 | |
| 	return
 | |
| }
 | |
| 
 | |
| func (z *bufioDecReader) unreadn1() {
 | |
| 	if z.c == 0 {
 | |
| 		halt.onerror(errDecUnreadByteNothingToRead)
 | |
| 	}
 | |
| 	z.c--
 | |
| 	z.n--
 | |
| }
 | |
| 
 | |
| func (z *bufioDecReader) readn2() (bs [2]byte) {
 | |
| 	z.readb(bs[:])
 | |
| 	return
 | |
| }
 | |
| 
 | |
| func (z *bufioDecReader) readn3() (bs [4]byte) {
 | |
| 	z.readb(bs[1:])
 | |
| 	return
 | |
| }
 | |
| 
 | |
| func (z *bufioDecReader) readn4() (bs [4]byte) {
 | |
| 	z.readb(bs[:])
 | |
| 	return
 | |
| }
 | |
| 
 | |
| func (z *bufioDecReader) readn8() (bs [8]byte) {
 | |
| 	z.readb(bs[:])
 | |
| 	return
 | |
| }
 | |
| 
 | |
| func (z *bufioDecReader) readx(n uint) (bs []byte) {
 | |
| 	if n == 0 {
 | |
| 		// return
 | |
| 	} else if z.c+n <= uint(len(z.buf)) {
 | |
| 		bs = z.buf[z.c : z.c+n]
 | |
| 		z.n += n
 | |
| 		z.c += n
 | |
| 	} else {
 | |
| 		bs = make([]byte, n)
 | |
| 		// n no longer used - can reuse
 | |
| 		n = uint(copy(bs, z.buf[z.c:]))
 | |
| 		z.n += n
 | |
| 		z.c += n
 | |
| 		z.readbFill(bs, n, true, false)
 | |
| 	}
 | |
| 	return
 | |
| }
 | |
| 
 | |
| func (z *bufioDecReader) jsonReadNum() (bs []byte) {
 | |
| 	z.unreadn1()
 | |
| 	z.bufr = z.bufr[:0]
 | |
| LOOP:
 | |
| 	i, eof := z.readn1eof()
 | |
| 	if eof {
 | |
| 		return z.bufr
 | |
| 	}
 | |
| 	if isNumberChar(i) {
 | |
| 		z.bufr = append(z.bufr, i)
 | |
| 		goto LOOP
 | |
| 	}
 | |
| 	z.unreadn1()
 | |
| 	return z.bufr
 | |
| }
 | |
| 
 | |
| func (z *bufioDecReader) jsonReadAsisChars() (bs []byte) {
 | |
| 	z.bufr = z.bufr[:0]
 | |
| LOOP:
 | |
| 	i := z.readn1()
 | |
| 	z.bufr = append(z.bufr, i)
 | |
| 	if i == '"' || i == '\\' {
 | |
| 		return z.bufr
 | |
| 	}
 | |
| 	goto LOOP
 | |
| }
 | |
| 
 | |
| func (z *bufioDecReader) skipWhitespace() (token byte) {
 | |
| 	i := z.c
 | |
| LOOP:
 | |
| 	if i < uint(len(z.buf)) {
 | |
| 		// inline z.skipLoopFn(i) and refactor, so cost is within inline budget
 | |
| 		token = z.buf[i]
 | |
| 		i++
 | |
| 		if isWhitespaceChar(token) {
 | |
| 			goto LOOP
 | |
| 		}
 | |
| 		z.n += i - 2 - z.c
 | |
| 		z.c = i
 | |
| 		return
 | |
| 	}
 | |
| 	return z.skipFillWhitespace()
 | |
| }
 | |
| 
 | |
| func (z *bufioDecReader) skipFillWhitespace() (token byte) {
 | |
| 	z.n += uint(len(z.buf)) - z.c
 | |
| 	var i, n2 int
 | |
| 	var err error
 | |
| 	for {
 | |
| 		z.c = 0
 | |
| 		z.buf = z.buf[0:cap(z.buf)]
 | |
| 		n2, err = z.r.Read(z.buf)
 | |
| 		if n2 == 0 {
 | |
| 			halt.onerror(err)
 | |
| 		}
 | |
| 		z.buf = z.buf[:n2]
 | |
| 		for i, token = range z.buf {
 | |
| 			if !isWhitespaceChar(token) {
 | |
| 				z.n += (uint(i) - z.c) - 1
 | |
| 				z.loopFn(uint(i + 1))
 | |
| 				return
 | |
| 			}
 | |
| 		}
 | |
| 		z.n += uint(n2)
 | |
| 	}
 | |
| }
 | |
| 
 | |
| func (z *bufioDecReader) loopFn(i uint) {
 | |
| 	z.c = i
 | |
| }
 | |
| 
 | |
| func (z *bufioDecReader) readUntil(stop byte) (out []byte) {
 | |
| 	i := z.c
 | |
| LOOP:
 | |
| 	if i < uint(len(z.buf)) {
 | |
| 		if z.buf[i] == stop {
 | |
| 			z.n += (i - z.c) - 1
 | |
| 			i++
 | |
| 			out = z.buf[z.c:i]
 | |
| 			z.c = i
 | |
| 			goto FINISH
 | |
| 		}
 | |
| 		i++
 | |
| 		goto LOOP
 | |
| 	}
 | |
| 	out = z.readUntilFill(stop)
 | |
| FINISH:
 | |
| 	return out[:len(out)-1]
 | |
| }
 | |
| 
 | |
| func (z *bufioDecReader) readUntilFill(stop byte) []byte {
 | |
| 	z.bufr = z.bufr[:0]
 | |
| 	z.n += uint(len(z.buf)) - z.c
 | |
| 	z.bufr = append(z.bufr, z.buf[z.c:]...)
 | |
| 	for {
 | |
| 		z.c = 0
 | |
| 		z.buf = z.buf[0:cap(z.buf)]
 | |
| 		n1, err := z.r.Read(z.buf)
 | |
| 		if n1 == 0 {
 | |
| 			halt.onerror(err)
 | |
| 		}
 | |
| 		n2 := uint(n1)
 | |
| 		z.buf = z.buf[:n2]
 | |
| 		for i, token := range z.buf {
 | |
| 			if token == stop {
 | |
| 				z.n += (uint(i) - z.c) - 1
 | |
| 				z.bufr = append(z.bufr, z.buf[z.c:i+1]...)
 | |
| 				z.loopFn(uint(i + 1))
 | |
| 				return z.bufr
 | |
| 			}
 | |
| 		}
 | |
| 		z.bufr = append(z.bufr, z.buf...)
 | |
| 		z.n += n2
 | |
| 	}
 | |
| }
 | |
| 
 | |
| // ------------------------------------
 | |
| 
 | |
| // bytesDecReader is a decReader that reads off a byte slice with zero copying
 | |
| //
 | |
| // Note: we do not try to convert index'ing out of bounds to an io.EOF.
 | |
| // instead, we let it bubble up to the exported Encode/Decode method
 | |
| // and recover it as an io.EOF.
 | |
| //
 | |
| // see panicValToErr(...) function in helper.go.
 | |
| type bytesDecReader struct {
 | |
| 	b []byte // data
 | |
| 	c uint   // cursor
 | |
| }
 | |
| 
 | |
| func (z *bytesDecReader) reset(in []byte) {
 | |
| 	z.b = in[:len(in):len(in)] // reslicing must not go past capacity
 | |
| 	z.c = 0
 | |
| }
 | |
| 
 | |
| func (z *bytesDecReader) numread() uint {
 | |
| 	return z.c
 | |
| }
 | |
| 
 | |
| // Note: slicing from a non-constant start position is more expensive,
 | |
| // as more computation is required to decipher the pointer start position.
 | |
| // However, we do it only once, and it's better than reslicing both z.b and return value.
 | |
| 
 | |
| func (z *bytesDecReader) readx(n uint) (bs []byte) {
 | |
| 	x := z.c + n
 | |
| 	bs = z.b[z.c:x]
 | |
| 	z.c = x
 | |
| 	return
 | |
| }
 | |
| 
 | |
| func (z *bytesDecReader) readb(bs []byte) {
 | |
| 	copy(bs, z.readx(uint(len(bs))))
 | |
| }
 | |
| 
 | |
| // MARKER: do not use this - as it calls into memmove (as the size of data to move is unknown)
 | |
| // func (z *bytesDecReader) readnn(bs []byte, n uint) {
 | |
| // 	x := z.c
 | |
| // 	copy(bs, z.b[x:x+n])
 | |
| // 	z.c += n
 | |
| // }
 | |
| 
 | |
| // func (z *bytesDecReader) readn(num uint8) (bs [8]byte) {
 | |
| // 	x := z.c + uint(num)
 | |
| // 	copy(bs[:], z.b[z.c:x]) // slice z.b completely, so we get bounds error if past
 | |
| // 	z.c = x
 | |
| // 	return
 | |
| // }
 | |
| 
 | |
| // func (z *bytesDecReader) readn1() uint8 {
 | |
| // 	z.c++
 | |
| // 	return z.b[z.c-1]
 | |
| // }
 | |
| 
 | |
| func (z *bytesDecReader) readn1() (v uint8) {
 | |
| 	v = z.b[z.c]
 | |
| 	z.c++
 | |
| 	return
 | |
| }
 | |
| 
 | |
| // MARKER: for readn{2,3,4,8}, ensure you slice z.b completely so we get bounds error if past end.
 | |
| 
 | |
| func (z *bytesDecReader) readn2() (bs [2]byte) {
 | |
| 	// copy(bs[:], z.b[z.c:z.c+2])
 | |
| 	bs[1] = z.b[z.c+1]
 | |
| 	bs[0] = z.b[z.c]
 | |
| 	z.c += 2
 | |
| 	return
 | |
| }
 | |
| 
 | |
| func (z *bytesDecReader) readn3() (bs [4]byte) {
 | |
| 	// copy(bs[1:], z.b[z.c:z.c+3])
 | |
| 	bs = okBytes3(z.b[z.c : z.c+3])
 | |
| 	z.c += 3
 | |
| 	return
 | |
| }
 | |
| 
 | |
| func (z *bytesDecReader) readn4() (bs [4]byte) {
 | |
| 	// copy(bs[:], z.b[z.c:z.c+4])
 | |
| 	bs = okBytes4(z.b[z.c : z.c+4])
 | |
| 	z.c += 4
 | |
| 	return
 | |
| }
 | |
| 
 | |
| func (z *bytesDecReader) readn8() (bs [8]byte) {
 | |
| 	// copy(bs[:], z.b[z.c:z.c+8])
 | |
| 	bs = okBytes8(z.b[z.c : z.c+8])
 | |
| 	z.c += 8
 | |
| 	return
 | |
| }
 | |
| 
 | |
| func (z *bytesDecReader) jsonReadNum() []byte {
 | |
| 	z.c--
 | |
| 	i := z.c
 | |
| LOOP:
 | |
| 	if i < uint(len(z.b)) && isNumberChar(z.b[i]) {
 | |
| 		i++
 | |
| 		goto LOOP
 | |
| 	}
 | |
| 	z.c, i = i, z.c
 | |
| 	return z.b[i:z.c]
 | |
| }
 | |
| 
 | |
| func (z *bytesDecReader) jsonReadAsisChars() []byte {
 | |
| 	i := z.c
 | |
| LOOP:
 | |
| 	token := z.b[i]
 | |
| 	i++
 | |
| 	if token == '"' || token == '\\' {
 | |
| 		z.c, i = i, z.c
 | |
| 		return z.b[i:z.c]
 | |
| 	}
 | |
| 	goto LOOP
 | |
| }
 | |
| 
 | |
| func (z *bytesDecReader) skipWhitespace() (token byte) {
 | |
| 	i := z.c
 | |
| LOOP:
 | |
| 	token = z.b[i]
 | |
| 	if isWhitespaceChar(token) {
 | |
| 		i++
 | |
| 		goto LOOP
 | |
| 	}
 | |
| 	z.c = i + 1
 | |
| 	return
 | |
| }
 | |
| 
 | |
| func (z *bytesDecReader) readUntil(stop byte) (out []byte) {
 | |
| 	i := z.c
 | |
| LOOP:
 | |
| 	if z.b[i] == stop {
 | |
| 		out = z.b[z.c:i]
 | |
| 		z.c = i + 1
 | |
| 		return
 | |
| 	}
 | |
| 	i++
 | |
| 	goto LOOP
 | |
| }
 | |
| 
 | |
| // --------------
 | |
| 
 | |
| type decRd struct {
 | |
| 	mtr bool // is maptype a known type?
 | |
| 	str bool // is slicetype a known type?
 | |
| 
 | |
| 	be   bool // is binary encoding
 | |
| 	js   bool // is json handle
 | |
| 	jsms bool // is json handle, and MapKeyAsString
 | |
| 	cbor bool // is cbor handle
 | |
| 
 | |
| 	bytes bool // is bytes reader
 | |
| 	bufio bool // is this a bufioDecReader?
 | |
| 
 | |
| 	rb bytesDecReader
 | |
| 	ri *ioDecReader
 | |
| 	bi *bufioDecReader
 | |
| 
 | |
| 	decReader
 | |
| }
 | |
| 
 | |
| // From out benchmarking, we see the following in terms of performance:
 | |
| //
 | |
| // - interface calls
 | |
| // - branch that can inline what it calls
 | |
| //
 | |
| // the if/else-if/else block is expensive to inline.
 | |
| // Each node of this construct costs a lot and dominates the budget.
 | |
| // Best to only do an if fast-path else block (so fast-path is inlined).
 | |
| // This is irrespective of inlineExtraCallCost set in $GOROOT/src/cmd/compile/internal/gc/inl.go
 | |
| //
 | |
| // In decRd methods below, we delegate all IO functions into their own methods.
 | |
| // This allows for the inlining of the common path when z.bytes=true.
 | |
| // Go 1.12+ supports inlining methods with up to 1 inlined function (or 2 if no other constructs).
 | |
| //
 | |
| // However, up through Go 1.13, decRd's readXXX, skip and unreadXXX methods are not inlined.
 | |
| // Consequently, there is no benefit to do the xxxIO methods for decRd at this time.
 | |
| // Instead, we have a if/else-if/else block so that IO calls do not have to jump through
 | |
| // a second unnecessary function call.
 | |
| //
 | |
| // If golang inlining gets better and bytesDecReader methods can be inlined,
 | |
| // then we can revert to using these 2 functions so the bytesDecReader
 | |
| // methods are inlined and the IO paths call out to a function.
 | |
| //
 | |
| // decRd is designed to embed a decReader, and then re-implement some of the decReader
 | |
| // methods using a conditional branch. We only override the ones that have a bytes version
 | |
| // that is small enough to be inlined. We use ./run.sh -z to check.
 | |
| // Right now, only numread and readn1 can be inlined.
 | |
| 
 | |
| func (z *decRd) numread() uint {
 | |
| 	if z.bytes {
 | |
| 		return z.rb.numread()
 | |
| 	} else if z.bufio {
 | |
| 		return z.bi.numread()
 | |
| 	} else {
 | |
| 		return z.ri.numread()
 | |
| 	}
 | |
| }
 | |
| 
 | |
| func (z *decRd) readn1() (v uint8) {
 | |
| 	if z.bytes {
 | |
| 		// MARKER: manually inline, else this function is not inlined.
 | |
| 		// Keep in sync with bytesDecReader.readn1
 | |
| 		// return z.rb.readn1()
 | |
| 		v = z.rb.b[z.rb.c]
 | |
| 		z.rb.c++
 | |
| 	} else {
 | |
| 		v = z.readn1IO()
 | |
| 	}
 | |
| 	return
 | |
| }
 | |
| func (z *decRd) readn1IO() uint8 {
 | |
| 	if z.bufio {
 | |
| 		return z.bi.readn1()
 | |
| 	}
 | |
| 	return z.ri.readn1()
 | |
| }
 | |
| 
 | |
| type devNullReader struct{}
 | |
| 
 | |
| func (devNullReader) Read(p []byte) (int, error) { return 0, io.EOF }
 | |
| func (devNullReader) Close() error               { return nil }
 | |
| 
 | |
| func readFull(r io.Reader, bs []byte) (n uint, err error) {
 | |
| 	var nn int
 | |
| 	for n < uint(len(bs)) && err == nil {
 | |
| 		nn, err = r.Read(bs[n:])
 | |
| 		if nn > 0 {
 | |
| 			if err == io.EOF {
 | |
| 				// leave EOF for next time
 | |
| 				err = nil
 | |
| 			}
 | |
| 			n += uint(nn)
 | |
| 		}
 | |
| 	}
 | |
| 	// do not do this below - it serves no purpose
 | |
| 	// if n != len(bs) && err == io.EOF { err = io.ErrUnexpectedEOF }
 | |
| 	return
 | |
| }
 | |
| 
 | |
| var _ decReader = (*decRd)(nil)
 |