package pgtype
import (
"database/sql/driver"
"encoding/binary"
"fmt"
"math"
"strconv"
"strings"
"github.com/jackc/pgx/v5/internal/pgio"
)
type LsegScanner interface {
ScanLseg (v Lseg ) error
}
type LsegValuer interface {
LsegValue () (Lseg , error )
}
type Lseg struct {
P [2 ]Vec2
Valid bool
}
func (lseg *Lseg ) ScanLseg (v Lseg ) error {
*lseg = v
return nil
}
func (lseg Lseg ) LsegValue () (Lseg , error ) {
return lseg , nil
}
func (lseg *Lseg ) Scan (src any ) error {
if src == nil {
*lseg = Lseg {}
return nil
}
switch src := src .(type ) {
case string :
return scanPlanTextAnyToLsegScanner {}.Scan ([]byte (src ), lseg )
}
return fmt .Errorf ("cannot scan %T" , src )
}
func (lseg Lseg ) Value () (driver .Value , error ) {
if !lseg .Valid {
return nil , nil
}
buf , err := LsegCodec {}.PlanEncode (nil , 0 , TextFormatCode , lseg ).Encode (lseg , nil )
if err != nil {
return nil , err
}
return string (buf ), err
}
type LsegCodec struct {}
func (LsegCodec ) FormatSupported (format int16 ) bool {
return format == TextFormatCode || format == BinaryFormatCode
}
func (LsegCodec ) PreferredFormat () int16 {
return BinaryFormatCode
}
func (LsegCodec ) PlanEncode (m *Map , oid uint32 , format int16 , value any ) EncodePlan {
if _ , ok := value .(LsegValuer ); !ok {
return nil
}
switch format {
case BinaryFormatCode :
return encodePlanLsegCodecBinary {}
case TextFormatCode :
return encodePlanLsegCodecText {}
}
return nil
}
type encodePlanLsegCodecBinary struct {}
func (encodePlanLsegCodecBinary ) Encode (value any , buf []byte ) (newBuf []byte , err error ) {
lseg , err := value .(LsegValuer ).LsegValue ()
if err != nil {
return nil , err
}
if !lseg .Valid {
return nil , nil
}
buf = pgio .AppendUint64 (buf , math .Float64bits (lseg .P [0 ].X ))
buf = pgio .AppendUint64 (buf , math .Float64bits (lseg .P [0 ].Y ))
buf = pgio .AppendUint64 (buf , math .Float64bits (lseg .P [1 ].X ))
buf = pgio .AppendUint64 (buf , math .Float64bits (lseg .P [1 ].Y ))
return buf , nil
}
type encodePlanLsegCodecText struct {}
func (encodePlanLsegCodecText ) Encode (value any , buf []byte ) (newBuf []byte , err error ) {
lseg , err := value .(LsegValuer ).LsegValue ()
if err != nil {
return nil , err
}
if !lseg .Valid {
return nil , nil
}
buf = append (buf , fmt .Sprintf (`[(%s,%s),(%s,%s)]` ,
strconv .FormatFloat (lseg .P [0 ].X , 'f' , -1 , 64 ),
strconv .FormatFloat (lseg .P [0 ].Y , 'f' , -1 , 64 ),
strconv .FormatFloat (lseg .P [1 ].X , 'f' , -1 , 64 ),
strconv .FormatFloat (lseg .P [1 ].Y , 'f' , -1 , 64 ),
)...)
return buf , nil
}
func (LsegCodec ) PlanScan (m *Map , oid uint32 , format int16 , target any ) ScanPlan {
switch format {
case BinaryFormatCode :
switch target .(type ) {
case LsegScanner :
return scanPlanBinaryLsegToLsegScanner {}
}
case TextFormatCode :
switch target .(type ) {
case LsegScanner :
return scanPlanTextAnyToLsegScanner {}
}
}
return nil
}
type scanPlanBinaryLsegToLsegScanner struct {}
func (scanPlanBinaryLsegToLsegScanner ) Scan (src []byte , dst any ) error {
scanner := (dst ).(LsegScanner )
if src == nil {
return scanner .ScanLseg (Lseg {})
}
if len (src ) != 32 {
return fmt .Errorf ("invalid length for lseg: %v" , len (src ))
}
x1 := binary .BigEndian .Uint64 (src )
y1 := binary .BigEndian .Uint64 (src [8 :])
x2 := binary .BigEndian .Uint64 (src [16 :])
y2 := binary .BigEndian .Uint64 (src [24 :])
return scanner .ScanLseg (Lseg {
P : [2 ]Vec2 {
{math .Float64frombits (x1 ), math .Float64frombits (y1 )},
{math .Float64frombits (x2 ), math .Float64frombits (y2 )},
},
Valid : true ,
})
}
type scanPlanTextAnyToLsegScanner struct {}
func (scanPlanTextAnyToLsegScanner ) Scan (src []byte , dst any ) error {
scanner := (dst ).(LsegScanner )
if src == nil {
return scanner .ScanLseg (Lseg {})
}
if len (src ) < 11 {
return fmt .Errorf ("invalid length for lseg: %v" , len (src ))
}
str := string (src [2 :])
var end int
end = strings .IndexByte (str , ',' )
x1 , err := strconv .ParseFloat (str [:end ], 64 )
if err != nil {
return err
}
str = str [end +1 :]
end = strings .IndexByte (str , ')' )
y1 , err := strconv .ParseFloat (str [:end ], 64 )
if err != nil {
return err
}
str = str [end +3 :]
end = strings .IndexByte (str , ',' )
x2 , err := strconv .ParseFloat (str [:end ], 64 )
if err != nil {
return err
}
str = str [end +1 : len (str )-2 ]
y2 , err := strconv .ParseFloat (str , 64 )
if err != nil {
return err
}
return scanner .ScanLseg (Lseg {P : [2 ]Vec2 {{x1 , y1 }, {x2 , y2 }}, Valid : true })
}
func (c LsegCodec ) DecodeDatabaseSQLValue (m *Map , oid uint32 , format int16 , src []byte ) (driver .Value , error ) {
return codecDecodeToTextFormat (c , m , oid , format , src )
}
func (c LsegCodec ) DecodeValue (m *Map , oid uint32 , format int16 , src []byte ) (any , error ) {
if src == nil {
return nil , nil
}
var lseg Lseg
err := codecScan (c , m , oid , format , src , &lseg )
if err != nil {
return nil , err
}
return lseg , nil
}
The pages are generated with Golds v0.6.7 . (GOOS=linux GOARCH=amd64)
Golds is a Go 101 project developed by Tapir Liu .
PR and bug reports are welcome and can be submitted to the issue list .
Please follow @Go100and1 (reachable from the left QR code) to get the latest news of Golds .