package pgtype

import (
	
	
	
)

type BytesScanner interface {
	// ScanBytes receives a byte slice of driver memory that is only valid until the next database method call.
	ScanBytes(v []byte) error
}

type BytesValuer interface {
	// BytesValue returns a byte slice of the byte data. The caller must not change the returned slice.
	BytesValue() ([]byte, error)
}

// DriverBytes is a byte slice that holds a reference to memory owned by the driver. It is only valid from the time it
// is scanned until Rows.Next or Rows.Close is called. It is never safe to use DriverBytes with QueryRow as Row.Scan
// internally calls Rows.Close before returning.
type DriverBytes []byte

func ( *DriverBytes) ( []byte) error {
	* = 
	return nil
}

// PreallocBytes is a byte slice of preallocated memory that scanned bytes will be copied to. If it is too small a new
// slice will be allocated.
type PreallocBytes []byte

func ( *PreallocBytes) ( []byte) error {
	if  == nil {
		* = nil
		return nil
	}

	if len() <= len(*) {
		* = (*)[:len()]
	} else {
		* = make(PreallocBytes, len())
	}
	copy(*, )
	return nil
}

// UndecodedBytes can be used as a scan target to get the raw bytes from PostgreSQL without any decoding.
type UndecodedBytes []byte

type scanPlanAnyToUndecodedBytes struct{}

func (scanPlanAnyToUndecodedBytes) ( []byte,  any) error {
	 := .(*UndecodedBytes)
	if  == nil {
		* = nil
		return nil
	}

	* = make([]byte, len())
	copy(*, )
	return nil
}

type ByteaCodec struct{}

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

func (ByteaCodec) () int16 {
	return BinaryFormatCode
}

func (ByteaCodec) ( *Map,  uint32,  int16,  any) EncodePlan {
	switch  {
	case BinaryFormatCode:
		switch .(type) {
		case []byte:
			return encodePlanBytesCodecBinaryBytes{}
		case BytesValuer:
			return encodePlanBytesCodecBinaryBytesValuer{}
		}
	case TextFormatCode:
		switch .(type) {
		case []byte:
			return encodePlanBytesCodecTextBytes{}
		case BytesValuer:
			return encodePlanBytesCodecTextBytesValuer{}
		}
	}

	return nil
}

type encodePlanBytesCodecBinaryBytes struct{}

func (encodePlanBytesCodecBinaryBytes) ( any,  []byte) ( []byte,  error) {
	 := .([]byte)
	if  == nil {
		return nil, nil
	}

	return append(, ...), nil
}

type encodePlanBytesCodecBinaryBytesValuer struct{}

func (encodePlanBytesCodecBinaryBytesValuer) ( any,  []byte) ( []byte,  error) {
	,  := .(BytesValuer).BytesValue()
	if  != nil {
		return nil, 
	}
	if  == nil {
		return nil, nil
	}

	return append(, ...), nil
}

type encodePlanBytesCodecTextBytes struct{}

func (encodePlanBytesCodecTextBytes) ( any,  []byte) ( []byte,  error) {
	 := .([]byte)
	if  == nil {
		return nil, nil
	}

	 = append(, `\x`...)
	 = append(, hex.EncodeToString()...)
	return , nil
}

type encodePlanBytesCodecTextBytesValuer struct{}

func (encodePlanBytesCodecTextBytesValuer) ( any,  []byte) ( []byte,  error) {
	,  := .(BytesValuer).BytesValue()
	if  != nil {
		return nil, 
	}
	if  == nil {
		return nil, nil
	}

	 = append(, `\x`...)
	 = append(, hex.EncodeToString()...)
	return , nil
}

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

	switch  {
	case BinaryFormatCode:
		switch .(type) {
		case *[]byte:
			return scanPlanBinaryBytesToBytes{}
		case BytesScanner:
			return scanPlanBinaryBytesToBytesScanner{}
		}
	case TextFormatCode:
		switch .(type) {
		case *[]byte:
			return scanPlanTextByteaToBytes{}
		case BytesScanner:
			return scanPlanTextByteaToBytesScanner{}
		}
	}

	return nil
}

type scanPlanBinaryBytesToBytes struct{}

func (scanPlanBinaryBytesToBytes) ( []byte,  any) error {
	 := .(*[]byte)
	if  == nil {
		* = nil
		return nil
	}

	* = make([]byte, len())
	copy(*, )
	return nil
}

type scanPlanBinaryBytesToBytesScanner struct{}

func (scanPlanBinaryBytesToBytesScanner) ( []byte,  any) error {
	 := ().(BytesScanner)
	return .ScanBytes()
}

type scanPlanTextByteaToBytes struct{}

func (scanPlanTextByteaToBytes) ( []byte,  any) error {
	 := .(*[]byte)
	if  == nil {
		* = nil
		return nil
	}

	,  := decodeHexBytea()
	if  != nil {
		return 
	}
	* = 

	return nil
}

type scanPlanTextByteaToBytesScanner struct{}

func (scanPlanTextByteaToBytesScanner) ( []byte,  any) error {
	 := ().(BytesScanner)
	,  := decodeHexBytea()
	if  != nil {
		return 
	}
	return .ScanBytes()
}

func decodeHexBytea( []byte) ([]byte, error) {
	if  == nil {
		return nil, nil
	}

	if len() < 2 || [0] != '\\' || [1] != 'x' {
		return nil, fmt.Errorf("invalid hex format")
	}

	 := make([]byte, (len()-2)/2)
	,  := hex.Decode(, [2:])
	if  != nil {
		return nil, 
	}

	return , nil
}

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

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

	var  []byte
	 := codecScan(, , , , , &)
	if  != nil {
		return nil, 
	}
	return , nil
}