package pgtype

import (
	
	
	
	
	

	
)

type TIDScanner interface {
	ScanTID(v TID) error
}

type TIDValuer interface {
	TIDValue() (TID, error)
}

// TID is PostgreSQL's Tuple Identifier type.
//
// When one does
//
//	select ctid, * from some_table;
//
// it is the data type of the ctid hidden system column.
//
// It is currently implemented as a pair unsigned two byte integers.
// Its conversion functions can be found in src/backend/utils/adt/tid.c
// in the PostgreSQL sources.
type TID struct {
	BlockNumber  uint32
	OffsetNumber uint16
	Valid        bool
}

func ( *TID) ( TID) error {
	* = 
	return nil
}

func ( TID) () (TID, error) {
	return , nil
}

// Scan implements the database/sql Scanner interface.
func ( *TID) ( any) error {
	if  == nil {
		* = TID{}
		return nil
	}

	switch src := .(type) {
	case string:
		return scanPlanTextAnyToTIDScanner{}.Scan([]byte(), )
	}

	return fmt.Errorf("cannot scan %T", )
}

// Value implements the database/sql/driver Valuer interface.
func ( TID) () (driver.Value, error) {
	if !.Valid {
		return nil, nil
	}

	,  := TIDCodec{}.PlanEncode(nil, 0, TextFormatCode, ).Encode(, nil)
	if  != nil {
		return nil, 
	}
	return string(), 
}

type TIDCodec struct{}

func (TIDCodec) ( int16) bool {
	return  == TextFormatCode ||  == BinaryFormatCode
}

func (TIDCodec) () int16 {
	return BinaryFormatCode
}

func (TIDCodec) ( *Map,  uint32,  int16,  any) EncodePlan {
	if ,  := .(TIDValuer); ! {
		return nil
	}

	switch  {
	case BinaryFormatCode:
		return encodePlanTIDCodecBinary{}
	case TextFormatCode:
		return encodePlanTIDCodecText{}
	}

	return nil
}

type encodePlanTIDCodecBinary struct{}

func (encodePlanTIDCodecBinary) ( any,  []byte) ( []byte,  error) {
	,  := .(TIDValuer).TIDValue()
	if  != nil {
		return nil, 
	}

	if !.Valid {
		return nil, nil
	}

	 = pgio.AppendUint32(, .BlockNumber)
	 = pgio.AppendUint16(, .OffsetNumber)
	return , nil
}

type encodePlanTIDCodecText struct{}

func (encodePlanTIDCodecText) ( any,  []byte) ( []byte,  error) {
	,  := .(TIDValuer).TIDValue()
	if  != nil {
		return nil, 
	}

	if !.Valid {
		return nil, nil
	}

	 = append(, fmt.Sprintf(`(%d,%d)`, .BlockNumber, .OffsetNumber)...)
	return , nil
}

func (TIDCodec) ( *Map,  uint32,  int16,  any) ScanPlan {

	switch  {
	case BinaryFormatCode:
		switch .(type) {
		case TIDScanner:
			return scanPlanBinaryTIDToTIDScanner{}
		case TextScanner:
			return scanPlanBinaryTIDToTextScanner{}
		}
	case TextFormatCode:
		switch .(type) {
		case TIDScanner:
			return scanPlanTextAnyToTIDScanner{}
		}
	}

	return nil
}

type scanPlanBinaryTIDToTIDScanner struct{}

func (scanPlanBinaryTIDToTIDScanner) ( []byte,  any) error {
	 := ().(TIDScanner)

	if  == nil {
		return .ScanTID(TID{})
	}

	if len() != 6 {
		return fmt.Errorf("invalid length for tid: %v", len())
	}

	return .ScanTID(TID{
		BlockNumber:  binary.BigEndian.Uint32(),
		OffsetNumber: binary.BigEndian.Uint16([4:]),
		Valid:        true,
	})
}

type scanPlanBinaryTIDToTextScanner struct{}

func (scanPlanBinaryTIDToTextScanner) ( []byte,  any) error {
	 := ().(TextScanner)

	if  == nil {
		return .ScanText(Text{})
	}

	if len() != 6 {
		return fmt.Errorf("invalid length for tid: %v", len())
	}

	 := binary.BigEndian.Uint32()
	 := binary.BigEndian.Uint16([4:])

	return .ScanText(Text{
		String: fmt.Sprintf(`(%d,%d)`, , ),
		Valid:  true,
	})
}

type scanPlanTextAnyToTIDScanner struct{}

func (scanPlanTextAnyToTIDScanner) ( []byte,  any) error {
	 := ().(TIDScanner)

	if  == nil {
		return .ScanTID(TID{})
	}

	if len() < 5 {
		return fmt.Errorf("invalid length for tid: %v", len())
	}

	 := strings.SplitN(string([1:len()-1]), ",", 2)
	if len() < 2 {
		return fmt.Errorf("invalid format for tid")
	}

	,  := strconv.ParseUint([0], 10, 32)
	if  != nil {
		return 
	}

	,  := strconv.ParseUint([1], 10, 16)
	if  != nil {
		return 
	}

	return .ScanTID(TID{BlockNumber: uint32(), OffsetNumber: uint16(), Valid: true})
}

func ( TIDCodec) ( *Map,  uint32,  int16,  []byte) (driver.Value, error) {
	return codecDecodeToTextFormat(, , , , )
}

func ( TIDCodec) ( *Map,  uint32,  int16,  []byte) (any, error) {
	if  == nil {
		return nil, nil
	}

	var  TID
	 := codecScan(, , , , , &)
	if  != nil {
		return nil, 
	}
	return , nil
}