package pgtype
import (
)
type BitsScanner interface {
ScanBits(v Bits) error
}
type BitsValuer interface {
BitsValue() (Bits, error)
}
type Bits struct {
Bytes []byte
Len int32
Valid bool
}
func ( *Bits) ( Bits) error {
* =
return nil
}
func ( Bits) () (Bits, error) {
return , nil
}
func ( *Bits) ( any) error {
if == nil {
* = Bits{}
return nil
}
switch src := .(type) {
case string:
return scanPlanTextAnyToBitsScanner{}.Scan([]byte(), )
}
return fmt.Errorf("cannot scan %T", )
}
func ( Bits) () (driver.Value, error) {
if !.Valid {
return nil, nil
}
, := BitsCodec{}.PlanEncode(nil, 0, TextFormatCode, ).Encode(, nil)
if != nil {
return nil,
}
return string(),
}
type BitsCodec struct{}
func (BitsCodec) ( int16) bool {
return == TextFormatCode || == BinaryFormatCode
}
func (BitsCodec) () int16 {
return BinaryFormatCode
}
func (BitsCodec) ( *Map, uint32, int16, any) EncodePlan {
if , := .(BitsValuer); ! {
return nil
}
switch {
case BinaryFormatCode:
return encodePlanBitsCodecBinary{}
case TextFormatCode:
return encodePlanBitsCodecText{}
}
return nil
}
type encodePlanBitsCodecBinary struct{}
func (encodePlanBitsCodecBinary) ( any, []byte) ( []byte, error) {
, := .(BitsValuer).BitsValue()
if != nil {
return nil,
}
if !.Valid {
return nil, nil
}
= pgio.AppendInt32(, .Len)
return append(, .Bytes...), nil
}
type encodePlanBitsCodecText struct{}
func (encodePlanBitsCodecText) ( any, []byte) ( []byte, error) {
, := .(BitsValuer).BitsValue()
if != nil {
return nil,
}
if !.Valid {
return nil, nil
}
for := int32(0); < .Len; ++ {
:= / 8
:= byte(128 >> byte(%8))
:= byte('0')
if .Bytes[]& > 0 {
= '1'
}
= append(, )
}
return , nil
}
func (BitsCodec) ( *Map, uint32, int16, any) ScanPlan {
switch {
case BinaryFormatCode:
switch .(type) {
case BitsScanner:
return scanPlanBinaryBitsToBitsScanner{}
}
case TextFormatCode:
switch .(type) {
case BitsScanner:
return scanPlanTextAnyToBitsScanner{}
}
}
return nil
}
func ( BitsCodec) ( *Map, uint32, int16, []byte) (driver.Value, error) {
return codecDecodeToTextFormat(, , , , )
}
func ( BitsCodec) ( *Map, uint32, int16, []byte) (any, error) {
if == nil {
return nil, nil
}
var Bits
:= codecScan(, , , , , &)
if != nil {
return nil,
}
return , nil
}
type scanPlanBinaryBitsToBitsScanner struct{}
func (scanPlanBinaryBitsToBitsScanner) ( []byte, any) error {
:= ().(BitsScanner)
if == nil {
return .ScanBits(Bits{})
}
if len() < 4 {
return fmt.Errorf("invalid length for bit/varbit: %v", len())
}
:= int32(binary.BigEndian.Uint32())
:= 4
:= make([]byte, len([:]))
copy(, [:])
return .ScanBits(Bits{Bytes: , Len: , Valid: true})
}
type scanPlanTextAnyToBitsScanner struct{}
func (scanPlanTextAnyToBitsScanner) ( []byte, any) error {
:= ().(BitsScanner)
if == nil {
return .ScanBits(Bits{})
}
:= len()
:= / 8
if %8 > 0 {
++
}
:= make([]byte, )
for , := range {
if == '1' {
:= / 8
:= uint( % 8)
[] = [] | (128 >> )
}
}
return .ScanBits(Bits{Bytes: , Len: int32(), Valid: true})
}