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