gotosocial/vendor/github.com/jackc/pgx/v5/pgtype/range.go
dependabot[bot] 3ab6214449
[chore]: Bump github.com/jackc/pgx/v5 from 5.5.0 to 5.5.1 (#2468)
Bumps [github.com/jackc/pgx/v5](https://github.com/jackc/pgx) from 5.5.0 to 5.5.1.
- [Changelog](https://github.com/jackc/pgx/blob/master/CHANGELOG.md)
- [Commits](https://github.com/jackc/pgx/compare/v5.5.0...v5.5.1)

---
updated-dependencies:
- dependency-name: github.com/jackc/pgx/v5
  dependency-type: direct:production
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2024-01-03 10:03:16 +00:00

323 lines
6.1 KiB
Go

package pgtype
import (
"bytes"
"encoding/binary"
"fmt"
)
type BoundType byte
const (
Inclusive = BoundType('i')
Exclusive = BoundType('e')
Unbounded = BoundType('U')
Empty = BoundType('E')
)
func (bt BoundType) String() string {
return string(bt)
}
type untypedTextRange struct {
Lower string
Upper string
LowerType BoundType
UpperType BoundType
}
func parseUntypedTextRange(src string) (*untypedTextRange, error) {
utr := &untypedTextRange{}
if src == "empty" {
utr.LowerType = Empty
utr.UpperType = Empty
return utr, nil
}
buf := bytes.NewBufferString(src)
skipWhitespace(buf)
r, _, err := buf.ReadRune()
if err != nil {
return nil, fmt.Errorf("invalid lower bound: %w", err)
}
switch r {
case '(':
utr.LowerType = Exclusive
case '[':
utr.LowerType = Inclusive
default:
return nil, fmt.Errorf("missing lower bound, instead got: %v", string(r))
}
r, _, err = buf.ReadRune()
if err != nil {
return nil, fmt.Errorf("invalid lower value: %w", err)
}
buf.UnreadRune()
if r == ',' {
utr.LowerType = Unbounded
} else {
utr.Lower, err = rangeParseValue(buf)
if err != nil {
return nil, fmt.Errorf("invalid lower value: %w", err)
}
}
r, _, err = buf.ReadRune()
if err != nil {
return nil, fmt.Errorf("missing range separator: %w", err)
}
if r != ',' {
return nil, fmt.Errorf("missing range separator: %v", r)
}
r, _, err = buf.ReadRune()
if err != nil {
return nil, fmt.Errorf("invalid upper value: %w", err)
}
if r == ')' || r == ']' {
utr.UpperType = Unbounded
} else {
buf.UnreadRune()
utr.Upper, err = rangeParseValue(buf)
if err != nil {
return nil, fmt.Errorf("invalid upper value: %w", err)
}
r, _, err = buf.ReadRune()
if err != nil {
return nil, fmt.Errorf("missing upper bound: %w", err)
}
switch r {
case ')':
utr.UpperType = Exclusive
case ']':
utr.UpperType = Inclusive
default:
return nil, fmt.Errorf("missing upper bound, instead got: %v", string(r))
}
}
skipWhitespace(buf)
if buf.Len() > 0 {
return nil, fmt.Errorf("unexpected trailing data: %v", buf.String())
}
return utr, nil
}
func rangeParseValue(buf *bytes.Buffer) (string, error) {
r, _, err := buf.ReadRune()
if err != nil {
return "", err
}
if r == '"' {
return rangeParseQuotedValue(buf)
}
buf.UnreadRune()
s := &bytes.Buffer{}
for {
r, _, err := buf.ReadRune()
if err != nil {
return "", err
}
switch r {
case '\\':
r, _, err = buf.ReadRune()
if err != nil {
return "", err
}
case ',', '[', ']', '(', ')':
buf.UnreadRune()
return s.String(), nil
}
s.WriteRune(r)
}
}
func rangeParseQuotedValue(buf *bytes.Buffer) (string, error) {
s := &bytes.Buffer{}
for {
r, _, err := buf.ReadRune()
if err != nil {
return "", err
}
switch r {
case '\\':
r, _, err = buf.ReadRune()
if err != nil {
return "", err
}
case '"':
r, _, err = buf.ReadRune()
if err != nil {
return "", err
}
if r != '"' {
buf.UnreadRune()
return s.String(), nil
}
}
s.WriteRune(r)
}
}
type untypedBinaryRange struct {
Lower []byte
Upper []byte
LowerType BoundType
UpperType BoundType
}
// 0 = () = 00000
// 1 = empty = 00001
// 2 = [) = 00010
// 4 = (] = 00100
// 6 = [] = 00110
// 8 = ) = 01000
// 12 = ] = 01100
// 16 = ( = 10000
// 18 = [ = 10010
// 24 = = 11000
const emptyMask = 1
const lowerInclusiveMask = 2
const upperInclusiveMask = 4
const lowerUnboundedMask = 8
const upperUnboundedMask = 16
func parseUntypedBinaryRange(src []byte) (*untypedBinaryRange, error) {
ubr := &untypedBinaryRange{}
if len(src) == 0 {
return nil, fmt.Errorf("range too short: %v", len(src))
}
rangeType := src[0]
rp := 1
if rangeType&emptyMask > 0 {
if len(src[rp:]) > 0 {
return nil, fmt.Errorf("unexpected trailing bytes parsing empty range: %v", len(src[rp:]))
}
ubr.LowerType = Empty
ubr.UpperType = Empty
return ubr, nil
}
if rangeType&lowerInclusiveMask > 0 {
ubr.LowerType = Inclusive
} else if rangeType&lowerUnboundedMask > 0 {
ubr.LowerType = Unbounded
} else {
ubr.LowerType = Exclusive
}
if rangeType&upperInclusiveMask > 0 {
ubr.UpperType = Inclusive
} else if rangeType&upperUnboundedMask > 0 {
ubr.UpperType = Unbounded
} else {
ubr.UpperType = Exclusive
}
if ubr.LowerType == Unbounded && ubr.UpperType == Unbounded {
if len(src[rp:]) > 0 {
return nil, fmt.Errorf("unexpected trailing bytes parsing unbounded range: %v", len(src[rp:]))
}
return ubr, nil
}
if len(src[rp:]) < 4 {
return nil, fmt.Errorf("too few bytes for size: %v", src[rp:])
}
valueLen := int(binary.BigEndian.Uint32(src[rp:]))
rp += 4
val := src[rp : rp+valueLen]
rp += valueLen
if ubr.LowerType != Unbounded {
ubr.Lower = val
} else {
ubr.Upper = val
if len(src[rp:]) > 0 {
return nil, fmt.Errorf("unexpected trailing bytes parsing range: %v", len(src[rp:]))
}
return ubr, nil
}
if ubr.UpperType != Unbounded {
if len(src[rp:]) < 4 {
return nil, fmt.Errorf("too few bytes for size: %v", src[rp:])
}
valueLen := int(binary.BigEndian.Uint32(src[rp:]))
rp += 4
ubr.Upper = src[rp : rp+valueLen]
rp += valueLen
}
if len(src[rp:]) > 0 {
return nil, fmt.Errorf("unexpected trailing bytes parsing range: %v", len(src[rp:]))
}
return ubr, nil
}
// Range is a generic range type.
type Range[T any] struct {
Lower T
Upper T
LowerType BoundType
UpperType BoundType
Valid bool
}
func (r Range[T]) IsNull() bool {
return !r.Valid
}
func (r Range[T]) BoundTypes() (lower, upper BoundType) {
return r.LowerType, r.UpperType
}
func (r Range[T]) Bounds() (lower, upper any) {
return &r.Lower, &r.Upper
}
func (r *Range[T]) ScanNull() error {
*r = Range[T]{}
return nil
}
func (r *Range[T]) ScanBounds() (lowerTarget, upperTarget any) {
return &r.Lower, &r.Upper
}
func (r *Range[T]) SetBoundTypes(lower, upper BoundType) error {
if lower == Unbounded || lower == Empty {
var zero T
r.Lower = zero
}
if upper == Unbounded || upper == Empty {
var zero T
r.Upper = zero
}
r.LowerType = lower
r.UpperType = upper
r.Valid = true
return nil
}