mirror of
https://github.com/superseriousbusiness/gotosocial.git
synced 2024-11-25 05:06:38 +00:00
ac6ed3d939
* upstep bun and sqlite versions * allow specific columns to be updated in the db * only update necessary columns for user * bit tidier * only update necessary fields of media_attachment * only update relevant instance fields * update tests * update only specific account columns * use bool pointers on gtsmodels includes attachment, status, account, user * update columns more selectively * test all default fields on new account insert * updating remaining bools on gtsmodels * initialize pointer fields when extracting AP emoji * copy bools properly * add copyBoolPtr convenience function + test it * initialize false bool ptrs a bit more neatly
134 lines
2 KiB
Go
134 lines
2 KiB
Go
package pgdialect
|
|
|
|
import (
|
|
"bytes"
|
|
"encoding/hex"
|
|
"fmt"
|
|
"io"
|
|
)
|
|
|
|
type arrayParser struct {
|
|
*streamParser
|
|
err error
|
|
}
|
|
|
|
func newArrayParser(b []byte) *arrayParser {
|
|
p := &arrayParser{
|
|
streamParser: newStreamParser(b, 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
|
|
}
|
|
if c == '\'' && next == '\'' {
|
|
p.buf = append(p.buf, next)
|
|
c, err = p.readByte()
|
|
if err != nil {
|
|
return nil, err
|
|
}
|
|
continue
|
|
}
|
|
|
|
p.buf = append(p.buf, c)
|
|
c = next
|
|
}
|
|
|
|
if bytes.HasPrefix(p.buf, []byte("\\x")) && len(p.buf)%2 == 0 {
|
|
data := p.buf[2:]
|
|
buf := make([]byte, hex.DecodedLen(len(data)))
|
|
n, err := hex.Decode(buf, data)
|
|
if err != nil {
|
|
return nil, err
|
|
}
|
|
return buf[:n], nil
|
|
}
|
|
|
|
return p.buf, nil
|
|
}
|