maeqtt/mqtt/properties/Properties.go

122 lines
1.9 KiB
Go

package properties
import (
"bufio"
"bytes"
"errors"
"io"
"badat.dev/maeqtt/v2/mqtt/types"
)
type Property interface {
id() int
parse(r *bufio.Reader) error
write(w io.Writer) error
hasValue() bool
}
func findMatchingProp(props []Property, id int) *Property {
for _, prop := range props {
if prop.id() == id {
return (&prop)
}
}
return nil
}
func ParseProperties(r *bufio.Reader, props []Property) error {
propLen, err := types.DecodeVariableByteInt(r)
if err != nil {
return err
}
limitReader := io.LimitReader(r, int64(propLen))
r = bufio.NewReader(limitReader)
for {
propId, err := r.ReadByte()
if err != nil {
if err == io.EOF {
break
} else {
return err
}
}
prop := findMatchingProp(props, int(propId))
if prop == nil {
return errors.New("Malformed packet invalid propid")
}
err = (*prop).parse(r)
if err != nil {
return err
}
}
return nil
}
func WriteProps(w io.Writer, props []Property) error {
buf := bytes.NewBuffer([]byte{})
for _, p := range props {
if p.hasValue() {
buf.Write([]byte{byte(p.id())})
err := p.write(buf)
if err != nil {
return err
}
}
}
return types.WriteDataWithVarIntLen(w, buf.Bytes())
}
type KVPair struct {
key string
value string
}
type UserProperty struct {
values []KVPair
}
func (*UserProperty) id() int {
return 38
}
func (u *UserProperty) parse(r *bufio.Reader) error {
key, err := types.DecodeUTF8String(r)
if err != nil {
return err
}
value, err := types.DecodeUTF8String(r)
if err != nil {
return err
}
u.values = append(u.values, KVPair{
key: key,
value: value,
})
return nil
}
func (u *UserProperty) write(w io.Writer) error {
for _, k := range u.values {
err := types.WriteUTF8String(w, k.key)
if err != nil {
return err
}
err = types.WriteUTF8String(w, k.value)
if err != nil {
return err
}
}
return nil
}
func (u *UserProperty) hasValue() bool {
return len(u.values) > 0
}