opentofu/config/string_list.go
Paul Hinze e88aeede9b core: allow distinguishing between empty lists and strings
Had to handle a lot of implicit leaning on a few properties of the old
representation:

 * Old representation allowed plain strings to be treated as lists
   without problem (i.e. shoved into strings.Split), now strings need to
   be checked whether they are a list before they are treated as one
   (i.e. shoved into StringList(s).Slice()).
 * Tested behavior of 0 and 1 length lists in formatlist() was a side
   effect of the representation. Needs to be special cased now to
   maintain the behavior.
 * Found a pretty old context test failure that was wrong in several
   different ways. It's covered by TestContext2Apply_multiVar so I
   removed it.
2015-06-25 18:53:35 -05:00

77 lines
1.8 KiB
Go

package config
import (
"fmt"
"strings"
)
// StringList represents the "poor man's list" that terraform uses
// internally
type StringList string
// This is the delimiter used to recognize and split StringLists
//
// It plays two semantic roles:
// * It introduces a list
// * It terminates each element
//
// Example representations:
// [] => SLD
// [""] => SLDSLD
// [" "] => SLD SLD
// ["foo"] => SLDfooSLD
// ["foo", "bar"] => SLDfooSLDbarSLD
// ["", ""] => SLDSLDSLD
const stringListDelim = `B780FFEC-B661-4EB8-9236-A01737AD98B6`
// Build a StringList from a slice
func NewStringList(parts []string) StringList {
// We have to special case the empty list representation
if len(parts) == 0 {
return StringList(stringListDelim)
}
return StringList(fmt.Sprintf("%s%s%s",
stringListDelim,
strings.Join(parts, stringListDelim),
stringListDelim,
))
}
// Returns an element at the index, wrapping around the length of the string
// when index > list length
func (sl StringList) Element(index int) string {
if sl.Length() == 0 {
return ""
}
return sl.Slice()[index%sl.Length()]
}
// Returns the length of the StringList
func (sl StringList) Length() int {
return len(sl.Slice())
}
// Returns a slice of strings as represented by this StringList
func (sl StringList) Slice() []string {
parts := strings.Split(string(sl), stringListDelim)
switch len(parts) {
case 0, 1:
return []string{}
case 2:
return []string{""}
}
// strip empty elements generated by leading and trailing delimiters
return parts[1 : len(parts)-1]
}
func (sl StringList) String() string {
return string(sl)
}
// Determines if a given string represents a StringList
func IsStringList(s string) bool {
return strings.Contains(s, stringListDelim)
}