59 lines
1.4 KiB
Go
59 lines
1.4 KiB
Go
package protocol
|
|
|
|
import "io"
|
|
import "fmt"
|
|
|
|
// Map is a string-to-string map with non-unique keys. Each key can be
|
|
// associated with multiple values. This is typically used for things like HTTP
|
|
// headers.
|
|
type Map map[string] []string
|
|
|
|
// ReadMap reads a map with a 16-bit length containing strings which have a
|
|
// 16-bit size. The length of the map corresponds to how many key/value pairs
|
|
// it has, and not how long the map is.
|
|
func ReadMap (reader io.Reader) (m Map, err error) {
|
|
length, err := ReadU16(reader)
|
|
if err != nil { return nil, err }
|
|
|
|
m = make(Map)
|
|
for length > 0 {
|
|
key, err := ReadString16(reader)
|
|
if err != nil { return m, err }
|
|
value, err := ReadString16(reader)
|
|
if err != nil { return m, err }
|
|
m.Add(key, value)
|
|
length --
|
|
}
|
|
|
|
return m, err
|
|
}
|
|
|
|
func (m Map) Serialize (writer io.Writer) (err error) {
|
|
if uint(len(m)) > MaxIntOfSize(2) {
|
|
panic(fmt.Sprintf("len(%d) cannot fit in U16", len(m)))
|
|
}
|
|
|
|
length := 0
|
|
for _, item := range m {
|
|
length += len(item)
|
|
}
|
|
|
|
err = WriteU16(writer, uint16(length))
|
|
if err != nil { return }
|
|
|
|
for key, values := range m {
|
|
for _, value := range values {
|
|
err = WriteString16(writer, key)
|
|
if err != nil { return }
|
|
err = WriteString16(writer, value)
|
|
if err != nil { return }
|
|
}}
|
|
|
|
return
|
|
}
|
|
|
|
// Add adds a value to the map under the specified key.
|
|
func (m Map) Add (key, value string) {
|
|
m[key] = append(m[key], value)
|
|
}
|