package pgdriver

import (
	
	
	
	
	
	
	
)

func ( string,  []driver.NamedValue) (string, error) {
	if len() == 0 {
		return , nil
	}

	 := make([]byte, 0, 2*len())

	 := newParser()
	for .Valid() {
		switch  := .Next();  {
		case '$':
			if ,  := .Number();  {
				if  > len() {
					return "", fmt.Errorf("pgdriver: got %d args, wanted %d", len(), )
				}

				var  error
				,  = appendArg(, [-1].Value)
				if  != nil {
					return "", 
				}
			} else {
				 = append(, '$')
			}
		case '\'':
			if ,  := .QuotedString();  {
				 = append(, ...)
			} else {
				 = append(, '\'')
			}
		default:
			 = append(, )
		}
	}

	return bytesToString(), nil
}

func ( []byte,  interface{}) ([]byte, error) {
	switch v := .(type) {
	case nil:
		return append(, "NULL"...), nil
	case int64:
		return strconv.AppendInt(, , 10), nil
	case float64:
		switch {
		case math.IsNaN():
			return append(, "'NaN'"...), nil
		case math.IsInf(, 1):
			return append(, "'Infinity'"...), nil
		case math.IsInf(, -1):
			return append(, "'-Infinity'"...), nil
		default:
			return strconv.AppendFloat(, , 'f', -1, 64), nil
		}
	case bool:
		if  {
			return append(, "TRUE"...), nil
		}
		return append(, "FALSE"...), nil
	case []byte:
		if  == nil {
			return append(, "NULL"...), nil
		}

		 = append(, `'\x`...)

		 := len()
		 = append(, make([]byte, hex.EncodedLen(len()))...)
		hex.Encode([:], )

		 = append(, "'"...)

		return , nil
	case string:
		 = append(, '\'')
		for ,  := range  {
			if  == '\000' {
				continue
			}

			if  == '\'' {
				 = append(, '\'', '\'')
				continue
			}

			if  < utf8.RuneSelf {
				 = append(, byte())
				continue
			}
			 := len()
			if cap()- < utf8.UTFMax {
				 = append(, make([]byte, utf8.UTFMax)...)
			}
			 := utf8.EncodeRune([:+utf8.UTFMax], )
			 = [:+]
		}
		 = append(, '\'')
		return , nil
	case time.Time:
		if .IsZero() {
			return append(, "NULL"...), nil
		}
		return .UTC().AppendFormat(, "'2006-01-02 15:04:05.999999-07:00'"), nil
	default:
		return nil, fmt.Errorf("pgdriver: unexpected arg: %T", )
	}
}

type parser struct {
	b []byte
	i int
}

func ( string) *parser {
	return &parser{
		b: stringToBytes(),
	}
}

func ( *parser) () bool {
	return .i < len(.b)
}

func ( *parser) () byte {
	 := .b[.i]
	.i++
	return 
}

func ( *parser) () (int, bool) {
	 := .i
	 := len(.b)

	for  := .i;  < len(.b); ++ {
		 := .b[]
		if !isNum() {
			 = 
			break
		}
	}

	.i = 
	 := .b[:]

	,  := strconv.Atoi(bytesToString())
	if  != nil {
		return 0, false
	}

	return , true
}

func ( *parser) () ([]byte, bool) {
	 := .i - 1
	 := len(.b)

	var  byte
	for  := .i;  < len(.b); ++ {
		 := .b[]
		if  == '\'' &&  != '\'' {
			 = 
			break
		}
		 = 
	}

	.i = 
	 := .b[:]

	return , true
}

func ( byte) bool {
	return  >= '0' &&  <= '9'
}