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