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