mirror of
https://github.com/superseriousbusiness/gotosocial.git
synced 2024-12-24 11:12:11 +00:00
147 lines
1.9 KiB
Go
147 lines
1.9 KiB
Go
|
package pgdialect
|
||
|
|
||
|
import (
|
||
|
"bytes"
|
||
|
"fmt"
|
||
|
"io"
|
||
|
)
|
||
|
|
||
|
type arrayParser struct {
|
||
|
b []byte
|
||
|
i int
|
||
|
|
||
|
buf []byte
|
||
|
err error
|
||
|
}
|
||
|
|
||
|
func newArrayParser(b []byte) *arrayParser {
|
||
|
p := &arrayParser{
|
||
|
b: b,
|
||
|
i: 1,
|
||
|
}
|
||
|
if len(b) < 2 || b[0] != '{' || b[len(b)-1] != '}' {
|
||
|
p.err = fmt.Errorf("bun: can't parse array: %q", b)
|
||
|
}
|
||
|
return p
|
||
|
}
|
||
|
|
||
|
func (p *arrayParser) NextElem() ([]byte, error) {
|
||
|
if p.err != nil {
|
||
|
return nil, p.err
|
||
|
}
|
||
|
|
||
|
c, err := p.readByte()
|
||
|
if err != nil {
|
||
|
return nil, err
|
||
|
}
|
||
|
|
||
|
switch c {
|
||
|
case '}':
|
||
|
return nil, io.EOF
|
||
|
case '"':
|
||
|
b, err := p.readSubstring()
|
||
|
if err != nil {
|
||
|
return nil, err
|
||
|
}
|
||
|
|
||
|
if p.peek() == ',' {
|
||
|
p.skipNext()
|
||
|
}
|
||
|
|
||
|
return b, nil
|
||
|
default:
|
||
|
b := p.readSimple()
|
||
|
if bytes.Equal(b, []byte("NULL")) {
|
||
|
b = nil
|
||
|
}
|
||
|
|
||
|
if p.peek() == ',' {
|
||
|
p.skipNext()
|
||
|
}
|
||
|
|
||
|
return b, nil
|
||
|
}
|
||
|
}
|
||
|
|
||
|
func (p *arrayParser) readSimple() []byte {
|
||
|
p.unreadByte()
|
||
|
|
||
|
if i := bytes.IndexByte(p.b[p.i:], ','); i >= 0 {
|
||
|
b := p.b[p.i : p.i+i]
|
||
|
p.i += i
|
||
|
return b
|
||
|
}
|
||
|
|
||
|
b := p.b[p.i : len(p.b)-1]
|
||
|
p.i = len(p.b) - 1
|
||
|
return b
|
||
|
}
|
||
|
|
||
|
func (p *arrayParser) readSubstring() ([]byte, error) {
|
||
|
c, err := p.readByte()
|
||
|
if err != nil {
|
||
|
return nil, err
|
||
|
}
|
||
|
|
||
|
p.buf = p.buf[:0]
|
||
|
for {
|
||
|
if c == '"' {
|
||
|
break
|
||
|
}
|
||
|
|
||
|
next, err := p.readByte()
|
||
|
if err != nil {
|
||
|
return nil, err
|
||
|
}
|
||
|
|
||
|
if c == '\\' {
|
||
|
switch next {
|
||
|
case '\\', '"':
|
||
|
p.buf = append(p.buf, next)
|
||
|
|
||
|
c, err = p.readByte()
|
||
|
if err != nil {
|
||
|
return nil, err
|
||
|
}
|
||
|
default:
|
||
|
p.buf = append(p.buf, '\\')
|
||
|
c = next
|
||
|
}
|
||
|
continue
|
||
|
}
|
||
|
|
||
|
p.buf = append(p.buf, c)
|
||
|
c = next
|
||
|
}
|
||
|
|
||
|
return p.buf, nil
|
||
|
}
|
||
|
|
||
|
func (p *arrayParser) valid() bool {
|
||
|
return p.i < len(p.b)
|
||
|
}
|
||
|
|
||
|
func (p *arrayParser) readByte() (byte, error) {
|
||
|
if p.valid() {
|
||
|
c := p.b[p.i]
|
||
|
p.i++
|
||
|
return c, nil
|
||
|
}
|
||
|
return 0, io.EOF
|
||
|
}
|
||
|
|
||
|
func (p *arrayParser) unreadByte() {
|
||
|
p.i--
|
||
|
}
|
||
|
|
||
|
func (p *arrayParser) peek() byte {
|
||
|
if p.valid() {
|
||
|
return p.b[p.i]
|
||
|
}
|
||
|
return 0
|
||
|
}
|
||
|
|
||
|
func (p *arrayParser) skipNext() {
|
||
|
p.i++
|
||
|
}
|