package pgtype
import (
)
type PolygonScanner interface {
ScanPolygon(v Polygon) error
}
type PolygonValuer interface {
PolygonValue() (Polygon, error)
}
type Polygon struct {
P []Vec2
Valid bool
}
func ( *Polygon) ( Polygon) error {
* =
return nil
}
func ( Polygon) () (Polygon, error) {
return , nil
}
func ( *Polygon) ( any) error {
if == nil {
* = Polygon{}
return nil
}
switch src := .(type) {
case string:
return scanPlanTextAnyToPolygonScanner{}.Scan([]byte(), )
}
return fmt.Errorf("cannot scan %T", )
}
func ( Polygon) () (driver.Value, error) {
if !.Valid {
return nil, nil
}
, := PolygonCodec{}.PlanEncode(nil, 0, TextFormatCode, ).Encode(, nil)
if != nil {
return nil,
}
return string(),
}
type PolygonCodec struct{}
func (PolygonCodec) ( int16) bool {
return == TextFormatCode || == BinaryFormatCode
}
func (PolygonCodec) () int16 {
return BinaryFormatCode
}
func (PolygonCodec) ( *Map, uint32, int16, any) EncodePlan {
if , := .(PolygonValuer); ! {
return nil
}
switch {
case BinaryFormatCode:
return encodePlanPolygonCodecBinary{}
case TextFormatCode:
return encodePlanPolygonCodecText{}
}
return nil
}
type encodePlanPolygonCodecBinary struct{}
func (encodePlanPolygonCodecBinary) ( any, []byte) ( []byte, error) {
, := .(PolygonValuer).PolygonValue()
if != nil {
return nil,
}
if !.Valid {
return nil, nil
}
= pgio.AppendInt32(, int32(len(.P)))
for , := range .P {
= pgio.AppendUint64(, math.Float64bits(.X))
= pgio.AppendUint64(, math.Float64bits(.Y))
}
return , nil
}
type encodePlanPolygonCodecText struct{}
func (encodePlanPolygonCodecText) ( any, []byte) ( []byte, error) {
, := .(PolygonValuer).PolygonValue()
if != nil {
return nil,
}
if !.Valid {
return nil, nil
}
= append(, '(')
for , := range .P {
if > 0 {
= append(, ',')
}
= append(, fmt.Sprintf(`(%s,%s)`,
strconv.FormatFloat(.X, 'f', -1, 64),
strconv.FormatFloat(.Y, 'f', -1, 64),
)...)
}
= append(, ')')
return , nil
}
func (PolygonCodec) ( *Map, uint32, int16, any) ScanPlan {
switch {
case BinaryFormatCode:
switch .(type) {
case PolygonScanner:
return scanPlanBinaryPolygonToPolygonScanner{}
}
case TextFormatCode:
switch .(type) {
case PolygonScanner:
return scanPlanTextAnyToPolygonScanner{}
}
}
return nil
}
type scanPlanBinaryPolygonToPolygonScanner struct{}
func (scanPlanBinaryPolygonToPolygonScanner) ( []byte, any) error {
:= ().(PolygonScanner)
if == nil {
return .ScanPolygon(Polygon{})
}
if len() < 5 {
return fmt.Errorf("invalid length for polygon: %v", len())
}
:= int(binary.BigEndian.Uint32())
:= 4
if 4+*16 != len() {
return fmt.Errorf("invalid length for Polygon with %d points: %v", , len())
}
:= make([]Vec2, )
for := range {
:= binary.BigEndian.Uint64([:])
+= 8
:= binary.BigEndian.Uint64([:])
+= 8
[] = Vec2{math.Float64frombits(), math.Float64frombits()}
}
return .ScanPolygon(Polygon{
P: ,
Valid: true,
})
}
type scanPlanTextAnyToPolygonScanner struct{}
func (scanPlanTextAnyToPolygonScanner) ( []byte, any) error {
:= ().(PolygonScanner)
if == nil {
return .ScanPolygon(Polygon{})
}
if len() < 7 {
return fmt.Errorf("invalid length for Polygon: %v", len())
}
:= make([]Vec2, 0)
:= string([2:])
for {
:= strings.IndexByte(, ',')
, := strconv.ParseFloat([:], 64)
if != nil {
return
}
= [+1:]
= strings.IndexByte(, ')')
, := strconv.ParseFloat([:], 64)
if != nil {
return
}
= append(, Vec2{, })
if +3 < len() {
= [+3:]
} else {
break
}
}
return .ScanPolygon(Polygon{P: , Valid: true})
}
func ( PolygonCodec) ( *Map, uint32, int16, []byte) (driver.Value, error) {
return codecDecodeToTextFormat(, , , , )
}
func ( PolygonCodec) ( *Map, uint32, int16, []byte) (any, error) {
if == nil {
return nil, nil
}
var Polygon
:= codecScan(, , , , , &)
if != nil {
return nil,
}
return , nil
}