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}