1package pgtype
2
3import (
4	"database/sql/driver"
5	"encoding/binary"
6	"fmt"
7	"math"
8	"strconv"
9	"strings"
10
11	"github.com/jackc/pgio"
12)
13
14type Circle struct {
15	P      Vec2
16	R      float64
17	Status Status
18}
19
20func (dst *Circle) Set(src interface{}) error {
21	return fmt.Errorf("cannot convert %v to Circle", src)
22}
23
24func (dst Circle) Get() interface{} {
25	switch dst.Status {
26	case Present:
27		return dst
28	case Null:
29		return nil
30	default:
31		return dst.Status
32	}
33}
34
35func (src *Circle) AssignTo(dst interface{}) error {
36	return fmt.Errorf("cannot assign %v to %T", src, dst)
37}
38
39func (dst *Circle) DecodeText(ci *ConnInfo, src []byte) error {
40	if src == nil {
41		*dst = Circle{Status: Null}
42		return nil
43	}
44
45	if len(src) < 9 {
46		return fmt.Errorf("invalid length for Circle: %v", len(src))
47	}
48
49	str := string(src[2:])
50	end := strings.IndexByte(str, ',')
51	x, err := strconv.ParseFloat(str[:end], 64)
52	if err != nil {
53		return err
54	}
55
56	str = str[end+1:]
57	end = strings.IndexByte(str, ')')
58
59	y, err := strconv.ParseFloat(str[:end], 64)
60	if err != nil {
61		return err
62	}
63
64	str = str[end+2 : len(str)-1]
65
66	r, err := strconv.ParseFloat(str, 64)
67	if err != nil {
68		return err
69	}
70
71	*dst = Circle{P: Vec2{x, y}, R: r, Status: Present}
72	return nil
73}
74
75func (dst *Circle) DecodeBinary(ci *ConnInfo, src []byte) error {
76	if src == nil {
77		*dst = Circle{Status: Null}
78		return nil
79	}
80
81	if len(src) != 24 {
82		return fmt.Errorf("invalid length for Circle: %v", len(src))
83	}
84
85	x := binary.BigEndian.Uint64(src)
86	y := binary.BigEndian.Uint64(src[8:])
87	r := binary.BigEndian.Uint64(src[16:])
88
89	*dst = Circle{
90		P:      Vec2{math.Float64frombits(x), math.Float64frombits(y)},
91		R:      math.Float64frombits(r),
92		Status: Present,
93	}
94	return nil
95}
96
97func (src Circle) EncodeText(ci *ConnInfo, buf []byte) ([]byte, error) {
98	switch src.Status {
99	case Null:
100		return nil, nil
101	case Undefined:
102		return nil, errUndefined
103	}
104
105	buf = append(buf, fmt.Sprintf(`<(%s,%s),%s>`,
106		strconv.FormatFloat(src.P.X, 'f', -1, 64),
107		strconv.FormatFloat(src.P.Y, 'f', -1, 64),
108		strconv.FormatFloat(src.R, 'f', -1, 64),
109	)...)
110
111	return buf, nil
112}
113
114func (src Circle) EncodeBinary(ci *ConnInfo, buf []byte) ([]byte, error) {
115	switch src.Status {
116	case Null:
117		return nil, nil
118	case Undefined:
119		return nil, errUndefined
120	}
121
122	buf = pgio.AppendUint64(buf, math.Float64bits(src.P.X))
123	buf = pgio.AppendUint64(buf, math.Float64bits(src.P.Y))
124	buf = pgio.AppendUint64(buf, math.Float64bits(src.R))
125	return buf, nil
126}
127
128// Scan implements the database/sql Scanner interface.
129func (dst *Circle) Scan(src interface{}) error {
130	if src == nil {
131		*dst = Circle{Status: Null}
132		return nil
133	}
134
135	switch src := src.(type) {
136	case string:
137		return dst.DecodeText(nil, []byte(src))
138	case []byte:
139		srcCopy := make([]byte, len(src))
140		copy(srcCopy, src)
141		return dst.DecodeText(nil, srcCopy)
142	}
143
144	return fmt.Errorf("cannot scan %T", src)
145}
146
147// Value implements the database/sql/driver Valuer interface.
148func (src Circle) Value() (driver.Value, error) {
149	return EncodeValueText(src)
150}
151