array.go

 1package query
 2
 3import (
 4	"fmt"
 5	"net/url"
 6)
 7
 8// Array represents the encoding of Query lists and sets. A Query array is a
 9// representation of a list of values of a fixed type. A serialized array might
10// look like the following:
11//
12//	ListName.member.1=foo
13//	&ListName.member.2=bar
14//	&Listname.member.3=baz
15type Array struct {
16	// The query values to add the array to.
17	values url.Values
18	// The array's prefix, which includes the names of all parent structures
19	// and ends with the name of the list. For example, the prefix might be
20	// "ParentStructure.ListName". This prefix will be used to form the full
21	// keys for each element in the list. For example, an entry might have the
22	// key "ParentStructure.ListName.member.MemberName.1".
23	//
24	// While this is currently represented as a string that gets added to, it
25	// could also be represented as a stack that only gets condensed into a
26	// string when a finalized key is created. This could potentially reduce
27	// allocations.
28	prefix string
29	// Whether the list is flat or not. A list that is not flat will produce the
30	// following entry to the url.Values for a given entry:
31	//     ListName.MemberName.1=value
32	// A list that is flat will produce the following:
33	//     ListName.1=value
34	flat bool
35	// The location name of the member. In most cases this should be "member".
36	memberName string
37	// Elements are stored in values, so we keep track of the list size here.
38	size int32
39	// Empty lists are encoded as "<prefix>=", if we add a value later we will
40	// remove this encoding
41	emptyValue Value
42}
43
44func newArray(values url.Values, prefix string, flat bool, memberName string) *Array {
45	emptyValue := newValue(values, prefix, flat)
46	emptyValue.String("")
47
48	return &Array{
49		values:     values,
50		prefix:     prefix,
51		flat:       flat,
52		memberName: memberName,
53		emptyValue: emptyValue,
54	}
55}
56
57// Value adds a new element to the Query Array. Returns a Value type used to
58// encode the array element.
59func (a *Array) Value() Value {
60	if a.size == 0 {
61		delete(a.values, a.emptyValue.key)
62	}
63
64	// Query lists start a 1, so adjust the size first
65	a.size++
66	prefix := a.prefix
67	if !a.flat {
68		prefix = fmt.Sprintf("%s.%s", prefix, a.memberName)
69	}
70	// Lists can't have flat members
71	return newValue(a.values, fmt.Sprintf("%s.%d", prefix, a.size), false)
72}