package pgtype

import (
	
	
	
	

	
)
ArrayType represents an array type. While it implements Value, this is only in service of its type conversion duties when registered as a data type in a ConnType. It should not be used directly as a Value. ArrayType is a convenience type for types that do not have an concrete array type.
type ArrayType struct {
	elements   []ValueTranscoder
	dimensions []ArrayDimension

	typeName   string
	newElement func() ValueTranscoder

	elementOID uint32
	status     Status
}

func ( string,  uint32,  func() ValueTranscoder) *ArrayType {
	return &ArrayType{typeName: , elementOID: , newElement: }
}

func ( *ArrayType) () Value {
	return &ArrayType{
		elements:   .elements,
		dimensions: .dimensions,
		status:     .status,

		typeName:   .typeName,
		elementOID: .elementOID,
		newElement: .newElement,
	}
}

func ( *ArrayType) () string {
	return .typeName
}

func ( *ArrayType) () {
	.elements = nil
	.dimensions = nil
	.status = Null
}

untyped nil and typed nil interfaces are different
	if  == nil {
		.setNil()
		return nil
	}

	 := reflect.ValueOf()
	if .Kind() != reflect.Slice {
		return fmt.Errorf("cannot set non-slice")
	}

	if .IsNil() {
		.setNil()
		return nil
	}

	.elements = make([]ValueTranscoder, .Len())
	for  := range .elements {
		 := .newElement()
		 := .Set(.Index().Interface())
		if  != nil {
			return 
		}

		.elements[] = 
	}
	.dimensions = []ArrayDimension{{Length: int32(len(.elements)), LowerBound: 1}}
	.status = Present

	return nil
}

func ( ArrayType) () interface{} {
	switch .status {
	case Present:
		 := make([]interface{}, len(.elements))
		for  := range .elements {
			[] = .elements[].Get()
		}
		return 
	case Null:
		return nil
	default:
		return .status
	}
}

func ( *ArrayType) ( interface{}) error {
	 := reflect.ValueOf()
	if .Kind() != reflect.Ptr {
		return fmt.Errorf("cannot assign to non-pointer")
	}

	 := .Elem()
	 := .Type()

	if .Kind() != reflect.Slice {
		return fmt.Errorf("cannot assign to pointer to non-slice")
	}

	switch .status {
	case Present:
		 := reflect.MakeSlice(, len(.elements), len(.elements))
		 := .Elem()

		for  := range .elements {
			 := reflect.New()
			 := .elements[].AssignTo(.Interface())
			if  != nil {
				return 
			}

			.Index().Set(.Elem())
		}

		.Set()
		return nil
	case Null:
		.Set(reflect.Zero())
		return nil
	}

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

func ( *ArrayType) ( *ConnInfo,  []byte) error {
	if  == nil {
		.setNil()
		return nil
	}

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

	var  []ValueTranscoder

	if len(.Elements) > 0 {
		 = make([]ValueTranscoder, len(.Elements))

		for ,  := range .Elements {
			 := .newElement()
			var  []byte
			if  != "NULL" {
				 = []byte()
			}
			 = .DecodeText(, )
			if  != nil {
				return 
			}

			[] = 
		}
	}

	.elements = 
	.dimensions = .Dimensions
	.status = Present

	return nil
}

func ( *ArrayType) ( *ConnInfo,  []byte) error {
	if  == nil {
		.setNil()
		return nil
	}

	var  ArrayHeader
	,  := .DecodeBinary(, )
	if  != nil {
		return 
	}

	var  []ValueTranscoder

	if len(.Dimensions) == 0 {
		.elements = 
		.dimensions = .Dimensions
		.status = Present
		return nil
	}

	 := .Dimensions[0].Length
	for ,  := range .Dimensions[1:] {
		 *= .Length
	}

	 = make([]ValueTranscoder, )

	for  := range  {
		 := .newElement()
		 := int(int32(binary.BigEndian.Uint32([:])))
		 += 4
		var  []byte
		if  >= 0 {
			 = [ : +]
			 += 
		}
		 = .DecodeBinary(, )
		if  != nil {
			return 
		}

		[] = 
	}

	.elements = 
	.dimensions = .Dimensions
	.status = Present

	return nil
}

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

	if len(.dimensions) == 0 {
		return append(, '{', '}'), nil
	}

	 = EncodeTextArrayDimensions(, .dimensions)
dimElemCounts is the multiples of elements that each array lies on. For example, a single dimension array of length 4 would have a dimElemCounts of [4]. A multi-dimensional array of lengths [3,5,2] would have a dimElemCounts of [30,10,2]. This is used to simplify when to render a '{' or '}'.
	 := make([]int, len(.dimensions))
	[len(.dimensions)-1] = int(.dimensions[len(.dimensions)-1].Length)
	for  := len(.dimensions) - 2;  > -1; -- {
		[] = int(.dimensions[].Length) * [+1]
	}

	 := make([]byte, 0, 32)
	for ,  := range .elements {
		if  > 0 {
			 = append(, ',')
		}

		for ,  := range  {
			if % == 0 {
				 = append(, '{')
			}
		}

		,  := .EncodeText(, )
		if  != nil {
			return nil, 
		}
		if  == nil {
			 = append(, `NULL`...)
		} else {
			 = append(, QuoteArrayElementIfNeeded(string())...)
		}

		for ,  := range  {
			if (+1)% == 0 {
				 = append(, '}')
			}
		}
	}

	return , nil
}

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

	 := ArrayHeader{
		Dimensions: .dimensions,
		ElementOID: int32(.elementOID),
	}

	for  := range .elements {
		if .elements[].Get() == nil {
			.ContainsNull = true
			break
		}
	}

	 = .EncodeBinary(, )

	for  := range .elements {
		 := len()
		 = pgio.AppendInt32(, -1)

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

	return , nil
}
Scan implements the database/sql Scanner interface.
func ( *ArrayType) ( interface{}) error {
	if  == nil {
		return .DecodeText(nil, 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 ( ArrayType) () (driver.Value, error) {
	,  := .EncodeText(nil, nil)
	if  != nil {
		return nil, 
	}
	if  == nil {
		return nil, nil
	}

	return string(), nil