1package eventstream
2
3import (
4	"encoding/binary"
5	"fmt"
6	"io"
7)
8
9// Headers are a collection of EventStream header values.
10type Headers []Header
11
12// Header is a single EventStream Key Value header pair.
13type Header struct {
14	Name  string
15	Value Value
16}
17
18// Set associates the name with a value. If the header name already exists in
19// the Headers the value will be replaced with the new one.
20func (hs *Headers) Set(name string, value Value) {
21	var i int
22	for ; i < len(*hs); i++ {
23		if (*hs)[i].Name == name {
24			(*hs)[i].Value = value
25			return
26		}
27	}
28
29	*hs = append(*hs, Header{
30		Name: name, Value: value,
31	})
32}
33
34// Get returns the Value associated with the header. Nil is returned if the
35// value does not exist.
36func (hs Headers) Get(name string) Value {
37	for i := 0; i < len(hs); i++ {
38		if h := hs[i]; h.Name == name {
39			return h.Value
40		}
41	}
42	return nil
43}
44
45// Del deletes the value in the Headers if it exists.
46func (hs *Headers) Del(name string) {
47	for i := 0; i < len(*hs); i++ {
48		if (*hs)[i].Name == name {
49			copy((*hs)[i:], (*hs)[i+1:])
50			(*hs) = (*hs)[:len(*hs)-1]
51		}
52	}
53}
54
55func decodeHeaders(r io.Reader) (Headers, error) {
56	hs := Headers{}
57
58	for {
59		name, err := decodeHeaderName(r)
60		if err != nil {
61			if err == io.EOF {
62				// EOF while getting header name means no more headers
63				break
64			}
65			return nil, err
66		}
67
68		value, err := decodeHeaderValue(r)
69		if err != nil {
70			return nil, err
71		}
72
73		hs.Set(name, value)
74	}
75
76	return hs, nil
77}
78
79func decodeHeaderName(r io.Reader) (string, error) {
80	var n headerName
81
82	var err error
83	n.Len, err = decodeUint8(r)
84	if err != nil {
85		return "", err
86	}
87
88	name := n.Name[:n.Len]
89	if _, err := io.ReadFull(r, name); err != nil {
90		return "", err
91	}
92
93	return string(name), nil
94}
95
96func decodeHeaderValue(r io.Reader) (Value, error) {
97	var raw rawValue
98
99	typ, err := decodeUint8(r)
100	if err != nil {
101		return nil, err
102	}
103	raw.Type = valueType(typ)
104
105	var v Value
106
107	switch raw.Type {
108	case trueValueType:
109		v = BoolValue(true)
110	case falseValueType:
111		v = BoolValue(false)
112	case int8ValueType:
113		var tv Int8Value
114		err = tv.decode(r)
115		v = tv
116	case int16ValueType:
117		var tv Int16Value
118		err = tv.decode(r)
119		v = tv
120	case int32ValueType:
121		var tv Int32Value
122		err = tv.decode(r)
123		v = tv
124	case int64ValueType:
125		var tv Int64Value
126		err = tv.decode(r)
127		v = tv
128	case bytesValueType:
129		var tv BytesValue
130		err = tv.decode(r)
131		v = tv
132	case stringValueType:
133		var tv StringValue
134		err = tv.decode(r)
135		v = tv
136	case timestampValueType:
137		var tv TimestampValue
138		err = tv.decode(r)
139		v = tv
140	case uuidValueType:
141		var tv UUIDValue
142		err = tv.decode(r)
143		v = tv
144	default:
145		panic(fmt.Sprintf("unknown value type %d", raw.Type))
146	}
147
148	// Error could be EOF, let caller deal with it
149	return v, err
150}
151
152const maxHeaderNameLen = 255
153
154type headerName struct {
155	Len  uint8
156	Name [maxHeaderNameLen]byte
157}
158
159func (v headerName) encode(w io.Writer) error {
160	if err := binary.Write(w, binary.BigEndian, v.Len); err != nil {
161		return err
162	}
163
164	_, err := w.Write(v.Name[:v.Len])
165	return err
166}
167