package pgtype

import (
	
	
	
	
	
	
	
	

	
)
Hstore represents an hstore column that can be null or have null values associated with its keys.
type Hstore struct {
	Map    map[string]Text
	Status Status
}

func ( *Hstore) ( interface{}) error {
	if  == nil {
		* = Hstore{Status: Null}
		return nil
	}

	if ,  := .(interface{ () interface{} });  {
		 := .()
		if  !=  {
			return .()
		}
	}

	switch value := .(type) {
	case map[string]string:
		 := make(map[string]Text, len())
		for ,  := range  {
			[] = Text{String: , Status: Present}
		}
		* = Hstore{Map: , Status: Present}
	default:
		return fmt.Errorf("cannot convert %v to Hstore", )
	}

	return nil
}

func ( Hstore) () interface{} {
	switch .Status {
	case Present:
		return .Map
	case Null:
		return nil
	default:
		return .Status
	}
}

func ( *Hstore) ( interface{}) error {
	switch .Status {
	case Present:
		switch v := .(type) {
		case *map[string]string:
			* = make(map[string]string, len(.Map))
			for ,  := range .Map {
				if .Status != Present {
					return fmt.Errorf("cannot decode %#v into %T", , )
				}
				(*)[] = .String
			}
			return nil
		default:
			if ,  := GetAssignToDstType();  {
				return .()
			}
			return fmt.Errorf("unable to assign to %T", )
		}
	case Null:
		return NullAssignTo()
	}

	return fmt.Errorf("cannot decode %#v into %T", , )
}

func ( *Hstore) ( *ConnInfo,  []byte) error {
	if  == nil {
		* = Hstore{Status: Null}
		return nil
	}

	, ,  := parseHstore(string())
	if  != nil {
		return 
	}

	 := make(map[string]Text, len())
	for  := range  {
		[[]] = []
	}

	* = Hstore{Map: , Status: Present}
	return nil
}

func ( *Hstore) ( *ConnInfo,  []byte) error {
	if  == nil {
		* = Hstore{Status: Null}
		return nil
	}

	 := 0

	if len([:]) < 4 {
		return fmt.Errorf("hstore incomplete %v", )
	}
	 := int(int32(binary.BigEndian.Uint32([:])))
	 += 4

	 := make(map[string]Text, )

	for  := 0;  < ; ++ {
		if len([:]) < 4 {
			return fmt.Errorf("hstore incomplete %v", )
		}
		 := int(int32(binary.BigEndian.Uint32([:])))
		 += 4

		if len([:]) <  {
			return fmt.Errorf("hstore incomplete %v", )
		}
		 := string([ : +])
		 += 

		if len([:]) < 4 {
			return fmt.Errorf("hstore incomplete %v", )
		}
		 := int(int32(binary.BigEndian.Uint32([:])))
		 += 4

		var  []byte
		if  >= 0 {
			 = [ : +]
		}
		 += 

		var  Text
		 := .DecodeBinary(, )
		if  != nil {
			return 
		}
		[] = 
	}

	* = Hstore{Map: , Status: Present}

	return nil
}

func ( Hstore) ( *ConnInfo,  []byte) ([]byte, error) {
	switch .Status {
	case Null:
		return nil, nil
	case Undefined:
		return nil, errUndefined
	}

	 := true

	 := make([]byte, 0, 32)
	for ,  := range .Map {
		if  {
			 = false
		} else {
			 = append(, ',')
		}

		 = append(, quoteHstoreElementIfNeeded()...)
		 = append(, "=>"...)

		,  := .EncodeText(, )
		if  != nil {
			return nil, 
		}

		if  == nil {
			 = append(, "NULL"...)
		} else {
			 = append(, quoteHstoreElementIfNeeded(string())...)
		}
	}

	return , nil
}

func ( Hstore) ( *ConnInfo,  []byte) ([]byte, error) {
	switch .Status {
	case Null:
		return nil, nil
	case Undefined:
		return nil, errUndefined
	}

	 = pgio.AppendInt32(, int32(len(.Map)))

	var  error
	for ,  := range .Map {
		 = pgio.AppendInt32(, int32(len()))
		 = append(, ...)

		 := len()
		 = pgio.AppendInt32(, -1)

		,  := .EncodeText(, )
		if  != nil {
			return nil, 
		}
		if  != nil {
			 = 
			pgio.SetInt32([:], int32(len([:])-4))
		}
	}

	return , 
}

var quoteHstoreReplacer = strings.NewReplacer(`\`, `\\`, `"`, `\"`)

func ( string) string {
	return `"` + quoteArrayReplacer.Replace() + `"`
}

func ( string) string {
	if  == "" || (len() == 4 && strings.ToLower() == "null") || strings.ContainsAny(, ` {},"\=>`) {
		return quoteArrayElement()
	}
	return 
}

const (
	hsPre = iota
	hsKey
	hsSep
	hsVal
	hsNul
	hsNext
)

type hstoreParser struct {
	str string
	pos int
}

func ( string) *hstoreParser {
	return &hstoreParser{
		pos: 0,
		str: ,
	}
}

func ( *hstoreParser) () ( rune,  bool) {
	if .pos >= len(.str) {
		 = true
		return
	}
	,  := utf8.DecodeRuneInString(.str[.pos:])
	.pos += 
	return
}

func ( *hstoreParser) () ( rune,  bool) {
	if .pos >= len(.str) {
		 = true
		return
	}
	, _ = utf8.DecodeRuneInString(.str[.pos:])
	return
}
parseHstore parses the string representation of an hstore column (the same you would get from an ordinary SELECT) into two slices of keys and values. it is used internally in the default parsing of hstores.
func ( string) ( []string,  []Text,  error) {
	if  == "" {
		return
	}

	 := bytes.Buffer{}
	 := []string{}
	 := []Text{}
	 := newHSP()

	,  := .Consume()
	 := hsPre

	for ! {
		switch  {
		case hsPre:
			if  == '"' {
				 = hsKey
			} else {
				 = errors.New("String does not begin with \"")
			}
		case hsKey:
			switch  {
			case '"': //End of the key
				 = append(, .String())
				 = bytes.Buffer{}
				 = hsSep
			case '\\': //Potential escaped character
				,  := .Consume()
				switch {
				case :
					 = errors.New("Found EOS in key, expecting character or \"")
				case  == '"',  == '\\':
					.WriteRune()
				default:
					.WriteRune()
					.WriteRune()
				}
			default: //Any other character
				.WriteRune()
			}
		case hsSep:
			if  == '=' {
				,  = .Consume()
				switch {
				case :
					 = errors.New("Found EOS after '=', expecting '>'")
				case  == '>':
					,  = .Consume()
					switch {
					case :
						 = errors.New("Found EOS after '=>', expecting '\"' or 'NULL'")
					case  == '"':
						 = hsVal
					case  == 'N':
						 = hsNul
					default:
						 = fmt.Errorf("Invalid character '%c' after '=>', expecting '\"' or 'NULL'", )
					}
				default:
					 = fmt.Errorf("Invalid character after '=', expecting '>'")
				}
			} else {
				 = fmt.Errorf("Invalid character '%c' after value, expecting '='", )
			}
		case hsVal:
			switch  {
			case '"': //End of the value
				 = append(, Text{String: .String(), Status: Present})
				 = bytes.Buffer{}
				 = hsNext
			case '\\': //Potential escaped character
				,  := .Consume()
				switch {
				case :
					 = errors.New("Found EOS in key, expecting character or \"")
				case  == '"',  == '\\':
					.WriteRune()
				default:
					.WriteRune()
					.WriteRune()
				}
			default: //Any other character
				.WriteRune()
			}
		case hsNul:
			 := make([]rune, 3)
			[0] = 
			for  := 1;  < 3; ++ {
				,  = .Consume()
				if  {
					 = errors.New("Found EOS in NULL value")
					return
				}
				[] = 
			}
			if [0] == 'U' && [1] == 'L' && [2] == 'L' {
				 = append(, Text{Status: Null})
				 = hsNext
			} else {
				 = fmt.Errorf("Invalid NULL value: 'N%s'", string())
			}
		case hsNext:
			if  == ',' {
				,  = .Consume()
				switch {
				case :
					 = errors.New("Found EOS after ',', expcting space")
				case (unicode.IsSpace()):
					,  = .Consume()
					 = hsKey
				default:
					 = fmt.Errorf("Invalid character '%c' after ', ', expecting \"", )
				}
			} else {
				 = fmt.Errorf("Invalid character '%c' after value, expecting ','", )
			}
		}

		if  != nil {
			return
		}
		,  = .Consume()
	}
	if  != hsNext {
		 = errors.New("Improperly formatted hstore")
		return
	}
	 = 
	 = 
	return
}
Scan implements the database/sql Scanner interface.
func ( *Hstore) ( interface{}) error {
	if  == nil {
		* = Hstore{Status: Null}
		return nil
	}

	switch src := .(type) {
	case string:
		return .DecodeText(nil, []byte())
	case []byte:
		 := make([]byte, len())
		copy(, )
		return .DecodeText(nil, )
	}

	return fmt.Errorf("cannot scan %T", )
}
Value implements the database/sql/driver Valuer interface.
func ( Hstore) () (driver.Value, error) {
	return EncodeValueText()