package pgtype

import (
	
	
	
	
	

	
)

type Uint64Scanner interface {
	ScanUint64(v Uint64) error
}

type Uint64Valuer interface {
	Uint64Value() (Uint64, error)
}

// Uint64 is the core type that is used to represent PostgreSQL types such as XID8.
type Uint64 struct {
	Uint64 uint64
	Valid  bool
}

// ScanUint64 implements the [Uint64Scanner] interface.
func ( *Uint64) ( Uint64) error {
	* = 
	return nil
}

// Uint64Value implements the [Uint64Valuer] interface.
func ( Uint64) () (Uint64, error) {
	return , nil
}

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

	var  uint64

	switch src := .(type) {
	case int64:
		if  < 0 {
			return fmt.Errorf("%d is less than the minimum value for Uint64", )
		}
		 = uint64()
	case string:
		,  := strconv.ParseUint(, 10, 64)
		if  != nil {
			return 
		}
		 = 
	default:
		return fmt.Errorf("cannot scan %T", )
	}

	* = Uint64{Uint64: , Valid: true}

	return nil
}

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

	// If the value is greater than the maximum value for int64, return it as a string instead of losing data or returning
	// an error.
	if .Uint64 > math.MaxInt64 {
		return strconv.FormatUint(.Uint64, 10), nil
	}

	return int64(.Uint64), nil
}

type Uint64Codec struct{}

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

func (Uint64Codec) () int16 {
	return BinaryFormatCode
}

func (Uint64Codec) ( *Map,  uint32,  int16,  any) EncodePlan {
	switch  {
	case BinaryFormatCode:
		switch .(type) {
		case uint64:
			return encodePlanUint64CodecBinaryUint64{}
		case Uint64Valuer:
			return encodePlanUint64CodecBinaryUint64Valuer{}
		case Int64Valuer:
			return encodePlanUint64CodecBinaryInt64Valuer{}
		}
	case TextFormatCode:
		switch .(type) {
		case uint64:
			return encodePlanUint64CodecTextUint64{}
		case Int64Valuer:
			return encodePlanUint64CodecTextInt64Valuer{}
		}
	}

	return nil
}

type encodePlanUint64CodecBinaryUint64 struct{}

func (encodePlanUint64CodecBinaryUint64) ( any,  []byte) ( []byte,  error) {
	 := .(uint64)
	return pgio.AppendUint64(, ), nil
}

type encodePlanUint64CodecBinaryUint64Valuer struct{}

func (encodePlanUint64CodecBinaryUint64Valuer) ( any,  []byte) ( []byte,  error) {
	,  := .(Uint64Valuer).Uint64Value()
	if  != nil {
		return nil, 
	}

	if !.Valid {
		return nil, nil
	}

	return pgio.AppendUint64(, .Uint64), nil
}

type encodePlanUint64CodecBinaryInt64Valuer struct{}

func (encodePlanUint64CodecBinaryInt64Valuer) ( any,  []byte) ( []byte,  error) {
	,  := .(Int64Valuer).Int64Value()
	if  != nil {
		return nil, 
	}

	if !.Valid {
		return nil, nil
	}

	if .Int64 < 0 {
		return nil, fmt.Errorf("%d is less than minimum value for uint64", .Int64)
	}

	return pgio.AppendUint64(, uint64(.Int64)), nil
}

type encodePlanUint64CodecTextUint64 struct{}

func (encodePlanUint64CodecTextUint64) ( any,  []byte) ( []byte,  error) {
	 := .(uint64)
	return append(, strconv.FormatUint(uint64(), 10)...), nil
}

type encodePlanUint64CodecTextUint64Valuer struct{}

func (encodePlanUint64CodecTextUint64Valuer) ( any,  []byte) ( []byte,  error) {
	,  := .(Uint64Valuer).Uint64Value()
	if  != nil {
		return nil, 
	}

	if !.Valid {
		return nil, nil
	}

	return append(, strconv.FormatUint(.Uint64, 10)...), nil
}

type encodePlanUint64CodecTextInt64Valuer struct{}

func (encodePlanUint64CodecTextInt64Valuer) ( any,  []byte) ( []byte,  error) {
	,  := .(Int64Valuer).Int64Value()
	if  != nil {
		return nil, 
	}

	if !.Valid {
		return nil, nil
	}

	if .Int64 < 0 {
		return nil, fmt.Errorf("%d is less than minimum value for uint64", .Int64)
	}

	return append(, strconv.FormatInt(.Int64, 10)...), nil
}

func (Uint64Codec) ( *Map,  uint32,  int16,  any) ScanPlan {
	switch  {
	case BinaryFormatCode:
		switch .(type) {
		case *uint64:
			return scanPlanBinaryUint64ToUint64{}
		case Uint64Scanner:
			return scanPlanBinaryUint64ToUint64Scanner{}
		case TextScanner:
			return scanPlanBinaryUint64ToTextScanner{}
		}
	case TextFormatCode:
		switch .(type) {
		case *uint64:
			return scanPlanTextAnyToUint64{}
		case Uint64Scanner:
			return scanPlanTextAnyToUint64Scanner{}
		}
	}

	return nil
}

func ( Uint64Codec) ( *Map,  uint32,  int16,  []byte) (driver.Value, error) {
	if  == nil {
		return nil, nil
	}

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

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

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

type scanPlanBinaryUint64ToUint64 struct{}

func (scanPlanBinaryUint64ToUint64) ( []byte,  any) error {
	if  == nil {
		return fmt.Errorf("cannot scan NULL into %T", )
	}

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

	 := ().(*uint64)
	* = binary.BigEndian.Uint64()

	return nil
}

type scanPlanBinaryUint64ToUint64Scanner struct{}

func (scanPlanBinaryUint64ToUint64Scanner) ( []byte,  any) error {
	,  := ().(Uint64Scanner)
	if ! {
		return ErrScanTargetTypeChanged
	}

	if  == nil {
		return .ScanUint64(Uint64{})
	}

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

	 := binary.BigEndian.Uint64()

	return .ScanUint64(Uint64{Uint64: , Valid: true})
}

type scanPlanBinaryUint64ToTextScanner struct{}

func (scanPlanBinaryUint64ToTextScanner) ( []byte,  any) error {
	,  := ().(TextScanner)
	if ! {
		return ErrScanTargetTypeChanged
	}

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

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

	 := uint64(binary.BigEndian.Uint64())
	return .ScanText(Text{String: strconv.FormatUint(, 10), Valid: true})
}

type scanPlanTextAnyToUint64Scanner struct{}

func (scanPlanTextAnyToUint64Scanner) ( []byte,  any) error {
	,  := ().(Uint64Scanner)
	if ! {
		return ErrScanTargetTypeChanged
	}

	if  == nil {
		return .ScanUint64(Uint64{})
	}

	,  := strconv.ParseUint(string(), 10, 64)
	if  != nil {
		return 
	}

	return .ScanUint64(Uint64{Uint64: , Valid: true})
}