...

Source file src/github.com/jackc/pgtype/aclitem_array.go

Documentation: github.com/jackc/pgtype

     1  // Code generated by erb. DO NOT EDIT.
     2  
     3  package pgtype
     4  
     5  import (
     6  	"database/sql/driver"
     7  	"fmt"
     8  	"reflect"
     9  )
    10  
    11  type ACLItemArray struct {
    12  	Elements   []ACLItem
    13  	Dimensions []ArrayDimension
    14  	Status     Status
    15  }
    16  
    17  func (dst *ACLItemArray) Set(src interface{}) error {
    18  	// untyped nil and typed nil interfaces are different
    19  	if src == nil {
    20  		*dst = ACLItemArray{Status: Null}
    21  		return nil
    22  	}
    23  
    24  	if value, ok := src.(interface{ Get() interface{} }); ok {
    25  		value2 := value.Get()
    26  		if value2 != value {
    27  			return dst.Set(value2)
    28  		}
    29  	}
    30  
    31  	// Attempt to match to select common types:
    32  	switch value := src.(type) {
    33  
    34  	case []string:
    35  		if value == nil {
    36  			*dst = ACLItemArray{Status: Null}
    37  		} else if len(value) == 0 {
    38  			*dst = ACLItemArray{Status: Present}
    39  		} else {
    40  			elements := make([]ACLItem, len(value))
    41  			for i := range value {
    42  				if err := elements[i].Set(value[i]); err != nil {
    43  					return err
    44  				}
    45  			}
    46  			*dst = ACLItemArray{
    47  				Elements:   elements,
    48  				Dimensions: []ArrayDimension{{Length: int32(len(elements)), LowerBound: 1}},
    49  				Status:     Present,
    50  			}
    51  		}
    52  
    53  	case []*string:
    54  		if value == nil {
    55  			*dst = ACLItemArray{Status: Null}
    56  		} else if len(value) == 0 {
    57  			*dst = ACLItemArray{Status: Present}
    58  		} else {
    59  			elements := make([]ACLItem, len(value))
    60  			for i := range value {
    61  				if err := elements[i].Set(value[i]); err != nil {
    62  					return err
    63  				}
    64  			}
    65  			*dst = ACLItemArray{
    66  				Elements:   elements,
    67  				Dimensions: []ArrayDimension{{Length: int32(len(elements)), LowerBound: 1}},
    68  				Status:     Present,
    69  			}
    70  		}
    71  
    72  	case []ACLItem:
    73  		if value == nil {
    74  			*dst = ACLItemArray{Status: Null}
    75  		} else if len(value) == 0 {
    76  			*dst = ACLItemArray{Status: Present}
    77  		} else {
    78  			*dst = ACLItemArray{
    79  				Elements:   value,
    80  				Dimensions: []ArrayDimension{{Length: int32(len(value)), LowerBound: 1}},
    81  				Status:     Present,
    82  			}
    83  		}
    84  	default:
    85  		// Fallback to reflection if an optimised match was not found.
    86  		// The reflection is necessary for arrays and multidimensional slices,
    87  		// but it comes with a 20-50% performance penalty for large arrays/slices
    88  		reflectedValue := reflect.ValueOf(src)
    89  		if !reflectedValue.IsValid() || reflectedValue.IsZero() {
    90  			*dst = ACLItemArray{Status: Null}
    91  			return nil
    92  		}
    93  
    94  		dimensions, elementsLength, ok := findDimensionsFromValue(reflectedValue, nil, 0)
    95  		if !ok {
    96  			return fmt.Errorf("cannot find dimensions of %v for ACLItemArray", src)
    97  		}
    98  		if elementsLength == 0 {
    99  			*dst = ACLItemArray{Status: Present}
   100  			return nil
   101  		}
   102  		if len(dimensions) == 0 {
   103  			if originalSrc, ok := underlyingSliceType(src); ok {
   104  				return dst.Set(originalSrc)
   105  			}
   106  			return fmt.Errorf("cannot convert %v to ACLItemArray", src)
   107  		}
   108  
   109  		*dst = ACLItemArray{
   110  			Elements:   make([]ACLItem, elementsLength),
   111  			Dimensions: dimensions,
   112  			Status:     Present,
   113  		}
   114  		elementCount, err := dst.setRecursive(reflectedValue, 0, 0)
   115  		if err != nil {
   116  			// Maybe the target was one dimension too far, try again:
   117  			if len(dst.Dimensions) > 1 {
   118  				dst.Dimensions = dst.Dimensions[:len(dst.Dimensions)-1]
   119  				elementsLength = 0
   120  				for _, dim := range dst.Dimensions {
   121  					if elementsLength == 0 {
   122  						elementsLength = int(dim.Length)
   123  					} else {
   124  						elementsLength *= int(dim.Length)
   125  					}
   126  				}
   127  				dst.Elements = make([]ACLItem, elementsLength)
   128  				elementCount, err = dst.setRecursive(reflectedValue, 0, 0)
   129  				if err != nil {
   130  					return err
   131  				}
   132  			} else {
   133  				return err
   134  			}
   135  		}
   136  		if elementCount != len(dst.Elements) {
   137  			return fmt.Errorf("cannot convert %v to ACLItemArray, expected %d dst.Elements, but got %d instead", src, len(dst.Elements), elementCount)
   138  		}
   139  	}
   140  
   141  	return nil
   142  }
   143  
   144  func (dst *ACLItemArray) setRecursive(value reflect.Value, index, dimension int) (int, error) {
   145  	switch value.Kind() {
   146  	case reflect.Array:
   147  		fallthrough
   148  	case reflect.Slice:
   149  		if len(dst.Dimensions) == dimension {
   150  			break
   151  		}
   152  
   153  		valueLen := value.Len()
   154  		if int32(valueLen) != dst.Dimensions[dimension].Length {
   155  			return 0, fmt.Errorf("multidimensional arrays must have array expressions with matching dimensions")
   156  		}
   157  		for i := 0; i < valueLen; i++ {
   158  			var err error
   159  			index, err = dst.setRecursive(value.Index(i), index, dimension+1)
   160  			if err != nil {
   161  				return 0, err
   162  			}
   163  		}
   164  
   165  		return index, nil
   166  	}
   167  	if !value.CanInterface() {
   168  		return 0, fmt.Errorf("cannot convert all values to ACLItemArray")
   169  	}
   170  	if err := dst.Elements[index].Set(value.Interface()); err != nil {
   171  		return 0, fmt.Errorf("%v in ACLItemArray", err)
   172  	}
   173  	index++
   174  
   175  	return index, nil
   176  }
   177  
   178  func (dst ACLItemArray) Get() interface{} {
   179  	switch dst.Status {
   180  	case Present:
   181  		return dst
   182  	case Null:
   183  		return nil
   184  	default:
   185  		return dst.Status
   186  	}
   187  }
   188  
   189  func (src *ACLItemArray) AssignTo(dst interface{}) error {
   190  	switch src.Status {
   191  	case Present:
   192  		if len(src.Dimensions) <= 1 {
   193  			// Attempt to match to select common types:
   194  			switch v := dst.(type) {
   195  
   196  			case *[]string:
   197  				*v = make([]string, len(src.Elements))
   198  				for i := range src.Elements {
   199  					if err := src.Elements[i].AssignTo(&((*v)[i])); err != nil {
   200  						return err
   201  					}
   202  				}
   203  				return nil
   204  
   205  			case *[]*string:
   206  				*v = make([]*string, len(src.Elements))
   207  				for i := range src.Elements {
   208  					if err := src.Elements[i].AssignTo(&((*v)[i])); err != nil {
   209  						return err
   210  					}
   211  				}
   212  				return nil
   213  
   214  			}
   215  		}
   216  
   217  		// Try to convert to something AssignTo can use directly.
   218  		if nextDst, retry := GetAssignToDstType(dst); retry {
   219  			return src.AssignTo(nextDst)
   220  		}
   221  
   222  		// Fallback to reflection if an optimised match was not found.
   223  		// The reflection is necessary for arrays and multidimensional slices,
   224  		// but it comes with a 20-50% performance penalty for large arrays/slices
   225  		value := reflect.ValueOf(dst)
   226  		if value.Kind() == reflect.Ptr {
   227  			value = value.Elem()
   228  		}
   229  
   230  		switch value.Kind() {
   231  		case reflect.Array, reflect.Slice:
   232  		default:
   233  			return fmt.Errorf("cannot assign %T to %T", src, dst)
   234  		}
   235  
   236  		if len(src.Elements) == 0 {
   237  			if value.Kind() == reflect.Slice {
   238  				value.Set(reflect.MakeSlice(value.Type(), 0, 0))
   239  				return nil
   240  			}
   241  		}
   242  
   243  		elementCount, err := src.assignToRecursive(value, 0, 0)
   244  		if err != nil {
   245  			return err
   246  		}
   247  		if elementCount != len(src.Elements) {
   248  			return fmt.Errorf("cannot assign %v, needed to assign %d elements, but only assigned %d", dst, len(src.Elements), elementCount)
   249  		}
   250  
   251  		return nil
   252  	case Null:
   253  		return NullAssignTo(dst)
   254  	}
   255  
   256  	return fmt.Errorf("cannot decode %#v into %T", src, dst)
   257  }
   258  
   259  func (src *ACLItemArray) assignToRecursive(value reflect.Value, index, dimension int) (int, error) {
   260  	switch kind := value.Kind(); kind {
   261  	case reflect.Array:
   262  		fallthrough
   263  	case reflect.Slice:
   264  		if len(src.Dimensions) == dimension {
   265  			break
   266  		}
   267  
   268  		length := int(src.Dimensions[dimension].Length)
   269  		if reflect.Array == kind {
   270  			typ := value.Type()
   271  			if typ.Len() != length {
   272  				return 0, fmt.Errorf("expected size %d array, but %s has size %d array", length, typ, typ.Len())
   273  			}
   274  			value.Set(reflect.New(typ).Elem())
   275  		} else {
   276  			value.Set(reflect.MakeSlice(value.Type(), length, length))
   277  		}
   278  
   279  		var err error
   280  		for i := 0; i < length; i++ {
   281  			index, err = src.assignToRecursive(value.Index(i), index, dimension+1)
   282  			if err != nil {
   283  				return 0, err
   284  			}
   285  		}
   286  
   287  		return index, nil
   288  	}
   289  	if len(src.Dimensions) != dimension {
   290  		return 0, fmt.Errorf("incorrect dimensions, expected %d, found %d", len(src.Dimensions), dimension)
   291  	}
   292  	if !value.CanAddr() {
   293  		return 0, fmt.Errorf("cannot assign all values from ACLItemArray")
   294  	}
   295  	addr := value.Addr()
   296  	if !addr.CanInterface() {
   297  		return 0, fmt.Errorf("cannot assign all values from ACLItemArray")
   298  	}
   299  	if err := src.Elements[index].AssignTo(addr.Interface()); err != nil {
   300  		return 0, err
   301  	}
   302  	index++
   303  	return index, nil
   304  }
   305  
   306  func (dst *ACLItemArray) DecodeText(ci *ConnInfo, src []byte) error {
   307  	if src == nil {
   308  		*dst = ACLItemArray{Status: Null}
   309  		return nil
   310  	}
   311  
   312  	uta, err := ParseUntypedTextArray(string(src))
   313  	if err != nil {
   314  		return err
   315  	}
   316  
   317  	var elements []ACLItem
   318  
   319  	if len(uta.Elements) > 0 {
   320  		elements = make([]ACLItem, len(uta.Elements))
   321  
   322  		for i, s := range uta.Elements {
   323  			var elem ACLItem
   324  			var elemSrc []byte
   325  			if s != "NULL" || uta.Quoted[i] {
   326  				elemSrc = []byte(s)
   327  			}
   328  			err = elem.DecodeText(ci, elemSrc)
   329  			if err != nil {
   330  				return err
   331  			}
   332  
   333  			elements[i] = elem
   334  		}
   335  	}
   336  
   337  	*dst = ACLItemArray{Elements: elements, Dimensions: uta.Dimensions, Status: Present}
   338  
   339  	return nil
   340  }
   341  
   342  func (src ACLItemArray) EncodeText(ci *ConnInfo, buf []byte) ([]byte, error) {
   343  	switch src.Status {
   344  	case Null:
   345  		return nil, nil
   346  	case Undefined:
   347  		return nil, errUndefined
   348  	}
   349  
   350  	if len(src.Dimensions) == 0 {
   351  		return append(buf, '{', '}'), nil
   352  	}
   353  
   354  	buf = EncodeTextArrayDimensions(buf, src.Dimensions)
   355  
   356  	// dimElemCounts is the multiples of elements that each array lies on. For
   357  	// example, a single dimension array of length 4 would have a dimElemCounts of
   358  	// [4]. A multi-dimensional array of lengths [3,5,2] would have a
   359  	// dimElemCounts of [30,10,2]. This is used to simplify when to render a '{'
   360  	// or '}'.
   361  	dimElemCounts := make([]int, len(src.Dimensions))
   362  	dimElemCounts[len(src.Dimensions)-1] = int(src.Dimensions[len(src.Dimensions)-1].Length)
   363  	for i := len(src.Dimensions) - 2; i > -1; i-- {
   364  		dimElemCounts[i] = int(src.Dimensions[i].Length) * dimElemCounts[i+1]
   365  	}
   366  
   367  	inElemBuf := make([]byte, 0, 32)
   368  	for i, elem := range src.Elements {
   369  		if i > 0 {
   370  			buf = append(buf, ',')
   371  		}
   372  
   373  		for _, dec := range dimElemCounts {
   374  			if i%dec == 0 {
   375  				buf = append(buf, '{')
   376  			}
   377  		}
   378  
   379  		elemBuf, err := elem.EncodeText(ci, inElemBuf)
   380  		if err != nil {
   381  			return nil, err
   382  		}
   383  		if elemBuf == nil {
   384  			buf = append(buf, `NULL`...)
   385  		} else {
   386  			buf = append(buf, QuoteArrayElementIfNeeded(string(elemBuf))...)
   387  		}
   388  
   389  		for _, dec := range dimElemCounts {
   390  			if (i+1)%dec == 0 {
   391  				buf = append(buf, '}')
   392  			}
   393  		}
   394  	}
   395  
   396  	return buf, nil
   397  }
   398  
   399  // Scan implements the database/sql Scanner interface.
   400  func (dst *ACLItemArray) Scan(src interface{}) error {
   401  	if src == nil {
   402  		return dst.DecodeText(nil, nil)
   403  	}
   404  
   405  	switch src := src.(type) {
   406  	case string:
   407  		return dst.DecodeText(nil, []byte(src))
   408  	case []byte:
   409  		srcCopy := make([]byte, len(src))
   410  		copy(srcCopy, src)
   411  		return dst.DecodeText(nil, srcCopy)
   412  	}
   413  
   414  	return fmt.Errorf("cannot scan %T", src)
   415  }
   416  
   417  // Value implements the database/sql/driver Valuer interface.
   418  func (src ACLItemArray) Value() (driver.Value, error) {
   419  	buf, err := src.EncodeText(nil, nil)
   420  	if err != nil {
   421  		return nil, err
   422  	}
   423  	if buf == nil {
   424  		return nil, nil
   425  	}
   426  
   427  	return string(buf), nil
   428  }
   429  

View as plain text