go/services/statestore/internal/resp/parse.go (83 lines of code) (raw):
// Copyright (c) Microsoft Corporation.
// Licensed under the MIT License.
package resp
import (
"bytes"
"fmt"
"strconv"
"strings"
"github.com/Azure/iot-operations-sdks/go/services/statestore/errors"
)
func PayloadError(format string, args ...any) errors.Payload {
return errors.Payload(fmt.Sprintf(format, args...))
}
func parseStr(typ byte, data []byte) (arg string, idx int, err error) {
sep := bytes.Index(data, separator)
if sep < 0 {
return "", 0, PayloadError("missing separator")
}
arg = string(data[1:sep])
idx = sep + len(separator)
switch data[0] {
case '-':
return "", 0, errors.Service(strings.TrimPrefix(arg, "ERR "))
case typ:
return arg, idx, nil
default:
return "", 0, PayloadError("wrong type %q", data[0])
}
}
func parseNum(typ byte, data []byte) (num, idx int, err error) {
val, idx, err := parseStr(typ, data)
if err != nil {
return 0, 0, err
}
num, err = strconv.Atoi(val)
if err != nil {
return 0, 0, PayloadError("invalid number %q", val)
}
return num, idx, nil
}
func parseBlob[T Bytes](typ byte, data []byte) (blob T, idx int, err error) {
var zero T
n, idx, err := parseNum(typ, data)
if err != nil {
return zero, 0, err
}
if n == -1 {
return zero, idx, nil
}
length := len(data) - idx - len(separator)
if length < n {
return zero, idx, PayloadError("insufficient data")
}
if data[idx+n] != separator[0] || data[idx+n+1] != separator[1] {
return zero, idx, PayloadError("missing separator")
}
return T(data[idx : idx+n]), idx + n + len(separator), nil
}
func String(data []byte) (string, error) {
str, _, err := parseStr('+', data)
return str, err
}
func Number(data []byte) (int, error) {
num, _, err := parseNum(':', data)
return num, err
}
func Blob[T Bytes](data []byte) (T, error) {
blob, _, err := parseBlob[T]('$', data)
return blob, err
}
func BlobArray[T Bytes](data []byte) ([]T, error) {
n, idx, err := parseNum('*', data)
if err != nil {
return nil, err
}
ary := make([]T, n)
for i := range n {
data = data[idx:]
ary[i], idx, err = parseBlob[T]('$', data)
if err != nil {
return nil, err
}
}
return ary, nil
}