gtsocial-umbx

Unnamed repository; edit this file 'description' to name the repository.
Log | Files | Refs | README | LICENSE

array_parser.go (2004B)


      1 package pgdialect
      2 
      3 import (
      4 	"bytes"
      5 	"encoding/hex"
      6 	"fmt"
      7 	"io"
      8 )
      9 
     10 type arrayParser struct {
     11 	*streamParser
     12 	err error
     13 }
     14 
     15 func newArrayParser(b []byte) *arrayParser {
     16 	p := &arrayParser{
     17 		streamParser: newStreamParser(b, 1),
     18 	}
     19 	if len(b) < 2 || b[0] != '{' || b[len(b)-1] != '}' {
     20 		p.err = fmt.Errorf("bun: can't parse array: %q", b)
     21 	}
     22 	return p
     23 }
     24 
     25 func (p *arrayParser) NextElem() ([]byte, error) {
     26 	if p.err != nil {
     27 		return nil, p.err
     28 	}
     29 
     30 	c, err := p.readByte()
     31 	if err != nil {
     32 		return nil, err
     33 	}
     34 
     35 	switch c {
     36 	case '}':
     37 		return nil, io.EOF
     38 	case '"':
     39 		b, err := p.readSubstring()
     40 		if err != nil {
     41 			return nil, err
     42 		}
     43 
     44 		if p.peek() == ',' {
     45 			p.skipNext()
     46 		}
     47 
     48 		return b, nil
     49 	default:
     50 		b := p.readSimple()
     51 		if bytes.Equal(b, []byte("NULL")) {
     52 			b = nil
     53 		}
     54 
     55 		if p.peek() == ',' {
     56 			p.skipNext()
     57 		}
     58 
     59 		return b, nil
     60 	}
     61 }
     62 
     63 func (p *arrayParser) readSimple() []byte {
     64 	p.unreadByte()
     65 
     66 	if i := bytes.IndexByte(p.b[p.i:], ','); i >= 0 {
     67 		b := p.b[p.i : p.i+i]
     68 		p.i += i
     69 		return b
     70 	}
     71 
     72 	b := p.b[p.i : len(p.b)-1]
     73 	p.i = len(p.b) - 1
     74 	return b
     75 }
     76 
     77 func (p *arrayParser) readSubstring() ([]byte, error) {
     78 	c, err := p.readByte()
     79 	if err != nil {
     80 		return nil, err
     81 	}
     82 
     83 	p.buf = p.buf[:0]
     84 	for {
     85 		if c == '"' {
     86 			break
     87 		}
     88 
     89 		next, err := p.readByte()
     90 		if err != nil {
     91 			return nil, err
     92 		}
     93 
     94 		if c == '\\' {
     95 			switch next {
     96 			case '\\', '"':
     97 				p.buf = append(p.buf, next)
     98 
     99 				c, err = p.readByte()
    100 				if err != nil {
    101 					return nil, err
    102 				}
    103 			default:
    104 				p.buf = append(p.buf, '\\')
    105 				c = next
    106 			}
    107 			continue
    108 		}
    109 		if c == '\'' && next == '\'' {
    110 			p.buf = append(p.buf, next)
    111 			c, err = p.readByte()
    112 			if err != nil {
    113 				return nil, err
    114 			}
    115 			continue
    116 		}
    117 
    118 		p.buf = append(p.buf, c)
    119 		c = next
    120 	}
    121 
    122 	if bytes.HasPrefix(p.buf, []byte("\\x")) && len(p.buf)%2 == 0 {
    123 		data := p.buf[2:]
    124 		buf := make([]byte, hex.DecodedLen(len(data)))
    125 		n, err := hex.Decode(buf, data)
    126 		if err != nil {
    127 			return nil, err
    128 		}
    129 		return buf[:n], nil
    130 	}
    131 
    132 	return p.buf, nil
    133 }