src

Go monorepo.
git clone git://code.dwrz.net/src
Log | Files | Refs

map.go (2951B)


      1 package query
      2 
      3 import (
      4 	"fmt"
      5 	"net/url"
      6 )
      7 
      8 // Map represents the encoding of Query maps. A Query map is a representation
      9 // of a mapping of arbitrary string keys to arbitrary values of a fixed type.
     10 // A Map differs from an Object in that the set of keys is not fixed, in that
     11 // the values must all be of the same type, and that map entries are ordered.
     12 // A serialized map might look like the following:
     13 //
     14 //	MapName.entry.1.key=Foo
     15 //	&MapName.entry.1.value=spam
     16 //	&MapName.entry.2.key=Bar
     17 //	&MapName.entry.2.value=eggs
     18 type Map struct {
     19 	// The query values to add the map to.
     20 	values url.Values
     21 	// The map's prefix, which includes the names of all parent structures
     22 	// and ends with the name of the object. For example, the prefix might be
     23 	// "ParentStructure.MapName". This prefix will be used to form the full
     24 	// keys for each key-value pair of the map. For example, a value might have
     25 	// the key "ParentStructure.MapName.1.value".
     26 	//
     27 	// While this is currently represented as a string that gets added to, it
     28 	// could also be represented as a stack that only gets condensed into a
     29 	// string when a finalized key is created. This could potentially reduce
     30 	// allocations.
     31 	prefix string
     32 	// Whether the map is flat or not. A map that is not flat will produce the
     33 	// following entries to the url.Values for a given key-value pair:
     34 	//     MapName.entry.1.KeyLocationName=mykey
     35 	//     MapName.entry.1.ValueLocationName=myvalue
     36 	// A map that is flat will produce the following:
     37 	//     MapName.1.KeyLocationName=mykey
     38 	//     MapName.1.ValueLocationName=myvalue
     39 	flat bool
     40 	// The location name of the key. In most cases this should be "key".
     41 	keyLocationName string
     42 	// The location name of the value. In most cases this should be "value".
     43 	valueLocationName string
     44 	// Elements are stored in values, so we keep track of the list size here.
     45 	size int32
     46 }
     47 
     48 func newMap(values url.Values, prefix string, flat bool, keyLocationName string, valueLocationName string) *Map {
     49 	return &Map{
     50 		values:            values,
     51 		prefix:            prefix,
     52 		flat:              flat,
     53 		keyLocationName:   keyLocationName,
     54 		valueLocationName: valueLocationName,
     55 	}
     56 }
     57 
     58 // Key adds the given named key to the Query map.
     59 // Returns a Value encoder that should be used to encode a Query value type.
     60 func (m *Map) Key(name string) Value {
     61 	// Query lists start a 1, so adjust the size first
     62 	m.size++
     63 	var key string
     64 	var value string
     65 	if m.flat {
     66 		key = fmt.Sprintf("%s.%d.%s", m.prefix, m.size, m.keyLocationName)
     67 		value = fmt.Sprintf("%s.%d.%s", m.prefix, m.size, m.valueLocationName)
     68 	} else {
     69 		key = fmt.Sprintf("%s.entry.%d.%s", m.prefix, m.size, m.keyLocationName)
     70 		value = fmt.Sprintf("%s.entry.%d.%s", m.prefix, m.size, m.valueLocationName)
     71 	}
     72 
     73 	// The key can only be a string, so we just go ahead and set it here
     74 	newValue(m.values, key, false).String(name)
     75 
     76 	// Maps can't have flat members
     77 	return newValue(m.values, value, false)
     78 }