1package pgtype 2 3import ( 4 "database/sql/driver" 5 "encoding/binary" 6 "fmt" 7 8 "github.com/jackc/pgio" 9) 10 11type Varbit struct { 12 Bytes []byte 13 Len int32 // Number of bits 14 Status Status 15} 16 17func (dst *Varbit) Set(src interface{}) error { 18 return fmt.Errorf("cannot convert %v to Varbit", src) 19} 20 21func (dst Varbit) Get() interface{} { 22 switch dst.Status { 23 case Present: 24 return dst 25 case Null: 26 return nil 27 default: 28 return dst.Status 29 } 30} 31 32func (src *Varbit) AssignTo(dst interface{}) error { 33 return fmt.Errorf("cannot assign %v to %T", src, dst) 34} 35 36func (dst *Varbit) DecodeText(ci *ConnInfo, src []byte) error { 37 if src == nil { 38 *dst = Varbit{Status: Null} 39 return nil 40 } 41 42 bitLen := len(src) 43 byteLen := bitLen / 8 44 if bitLen%8 > 0 { 45 byteLen++ 46 } 47 buf := make([]byte, byteLen) 48 49 for i, b := range src { 50 if b == '1' { 51 byteIdx := i / 8 52 bitIdx := uint(i % 8) 53 buf[byteIdx] = buf[byteIdx] | (128 >> bitIdx) 54 } 55 } 56 57 *dst = Varbit{Bytes: buf, Len: int32(bitLen), Status: Present} 58 return nil 59} 60 61func (dst *Varbit) DecodeBinary(ci *ConnInfo, src []byte) error { 62 if src == nil { 63 *dst = Varbit{Status: Null} 64 return nil 65 } 66 67 if len(src) < 4 { 68 return fmt.Errorf("invalid length for varbit: %v", len(src)) 69 } 70 71 bitLen := int32(binary.BigEndian.Uint32(src)) 72 rp := 4 73 74 *dst = Varbit{Bytes: src[rp:], Len: bitLen, Status: Present} 75 return nil 76} 77 78func (src Varbit) EncodeText(ci *ConnInfo, buf []byte) ([]byte, error) { 79 switch src.Status { 80 case Null: 81 return nil, nil 82 case Undefined: 83 return nil, errUndefined 84 } 85 86 for i := int32(0); i < src.Len; i++ { 87 byteIdx := i / 8 88 bitMask := byte(128 >> byte(i%8)) 89 char := byte('0') 90 if src.Bytes[byteIdx]&bitMask > 0 { 91 char = '1' 92 } 93 buf = append(buf, char) 94 } 95 96 return buf, nil 97} 98 99func (src Varbit) EncodeBinary(ci *ConnInfo, buf []byte) ([]byte, error) { 100 switch src.Status { 101 case Null: 102 return nil, nil 103 case Undefined: 104 return nil, errUndefined 105 } 106 107 buf = pgio.AppendInt32(buf, src.Len) 108 return append(buf, src.Bytes...), nil 109} 110 111// Scan implements the database/sql Scanner interface. 112func (dst *Varbit) Scan(src interface{}) error { 113 if src == nil { 114 *dst = Varbit{Status: Null} 115 return nil 116 } 117 118 switch src := src.(type) { 119 case string: 120 return dst.DecodeText(nil, []byte(src)) 121 case []byte: 122 srcCopy := make([]byte, len(src)) 123 copy(srcCopy, src) 124 return dst.DecodeText(nil, srcCopy) 125 } 126 127 return fmt.Errorf("cannot scan %T", src) 128} 129 130// Value implements the database/sql/driver Valuer interface. 131func (src Varbit) Value() (driver.Value, error) { 132 return EncodeValueText(src) 133} 134