Wrote roots-ws golang implementation.
This commit is contained in:
324
envelope/find.go
Normal file
324
envelope/find.go
Normal file
@@ -0,0 +1,324 @@
|
||||
package envelope
|
||||
|
||||
import (
|
||||
"encoding/json"
|
||||
"fmt"
|
||||
"git.wisehodl.dev/jay/go-roots-ws/errors"
|
||||
)
|
||||
|
||||
// CheckArrayLength is a helper function that ensures the JSON array has at
|
||||
// least the minimum length required
|
||||
func CheckArrayLength(arr []json.RawMessage, minLen int) error {
|
||||
if len(arr) < minLen {
|
||||
return fmt.Errorf("%w: expected %d elements, got %d", errors.InvalidEnvelope, minLen, len(arr))
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
// CheckLabel is a helper function that verifies that the envelope label
|
||||
// matches the expected one
|
||||
func CheckLabel(got, want string) error {
|
||||
if got != want {
|
||||
return fmt.Errorf("%w: expected %s, got %s", errors.WrongEnvelopeLabel, want, got)
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
// ParseElement is a helper function that unmarshals an array element into the
|
||||
// provided value
|
||||
func ParseElement(element json.RawMessage, value interface{}, position string) error {
|
||||
if err := json.Unmarshal(element, value); err != nil {
|
||||
return fmt.Errorf("%w: %s is not the expected type", errors.WrongFieldType, position)
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
// FindEvent extracts an event from an EVENT envelope with no subscription ID.
|
||||
// Expected Format: ["EVENT", event]
|
||||
func FindEvent(env Envelope) ([]byte, error) {
|
||||
var arr []json.RawMessage
|
||||
if err := json.Unmarshal(env, &arr); err != nil {
|
||||
return nil, fmt.Errorf("%w: %v", errors.InvalidJSON, err)
|
||||
}
|
||||
|
||||
if err := CheckArrayLength(arr, 2); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
var label string
|
||||
if err := ParseElement(arr[0], &label, "envelope label"); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
if err := CheckLabel(label, "EVENT"); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
return arr[1], nil
|
||||
}
|
||||
|
||||
// FindSubscriptionEvent extracts an event and subscription ID from an EVENT envelope.
|
||||
// Expected Format: ["EVENT", subID, event]
|
||||
func FindSubscriptionEvent(env Envelope) (subID string, event []byte, err error) {
|
||||
var arr []json.RawMessage
|
||||
if err = json.Unmarshal(env, &arr); err != nil {
|
||||
return "", nil, fmt.Errorf("%w: %v", errors.InvalidJSON, err)
|
||||
}
|
||||
|
||||
if err = CheckArrayLength(arr, 3); err != nil {
|
||||
return "", nil, err
|
||||
}
|
||||
|
||||
var label string
|
||||
if err := ParseElement(arr[0], &label, "envelope label"); err != nil {
|
||||
return "", nil, err
|
||||
}
|
||||
|
||||
if err = CheckLabel(label, "EVENT"); err != nil {
|
||||
return "", nil, err
|
||||
}
|
||||
|
||||
if err = ParseElement(arr[1], &subID, "subscription ID"); err != nil {
|
||||
return "", nil, err
|
||||
}
|
||||
|
||||
return subID, arr[2], nil
|
||||
}
|
||||
|
||||
// FindOK extracts eventID, status, and message from an OK envelope.
|
||||
// Expected Format: ["OK", eventID, status, message]
|
||||
func FindOK(env Envelope) (eventID string, status bool, message string, err error) {
|
||||
var arr []json.RawMessage
|
||||
if err = json.Unmarshal(env, &arr); err != nil {
|
||||
return "", false, "", fmt.Errorf("%w: %v", errors.InvalidJSON, err)
|
||||
}
|
||||
|
||||
if err = CheckArrayLength(arr, 4); err != nil {
|
||||
return "", false, "", err
|
||||
}
|
||||
|
||||
var label string
|
||||
if err := ParseElement(arr[0], &label, "envelope label"); err != nil {
|
||||
return "", false, "", err
|
||||
}
|
||||
|
||||
if err = CheckLabel(label, "OK"); err != nil {
|
||||
return "", false, "", err
|
||||
}
|
||||
|
||||
if err = ParseElement(arr[1], &eventID, "event ID"); err != nil {
|
||||
return "", false, "", err
|
||||
}
|
||||
|
||||
if err = ParseElement(arr[2], &status, "status"); err != nil {
|
||||
return "", false, "", err
|
||||
}
|
||||
|
||||
if err = ParseElement(arr[3], &message, "message"); err != nil {
|
||||
return "", false, "", err
|
||||
}
|
||||
|
||||
return eventID, status, message, nil
|
||||
}
|
||||
|
||||
// FindReq extracts subscription ID and filters from a REQ envelope.
|
||||
// Expected Format: ["REQ", subID, filter1, filter2, ...]
|
||||
func FindReq(env Envelope) (subID string, filters [][]byte, err error) {
|
||||
var arr []json.RawMessage
|
||||
if err = json.Unmarshal(env, &arr); err != nil {
|
||||
return "", nil, fmt.Errorf("%w: %v", errors.InvalidJSON, err)
|
||||
}
|
||||
|
||||
if err = CheckArrayLength(arr, 2); err != nil {
|
||||
return "", nil, err
|
||||
}
|
||||
|
||||
var label string
|
||||
if err := ParseElement(arr[0], &label, "envelope label"); err != nil {
|
||||
return "", nil, err
|
||||
}
|
||||
|
||||
if err = CheckLabel(label, "REQ"); err != nil {
|
||||
return "", nil, err
|
||||
}
|
||||
|
||||
if err = ParseElement(arr[1], &subID, "subscription ID"); err != nil {
|
||||
return "", nil, err
|
||||
}
|
||||
|
||||
filters = make([][]byte, 0, len(arr)-2)
|
||||
for i := 2; i < len(arr); i++ {
|
||||
filters = append(filters, arr[i])
|
||||
}
|
||||
|
||||
return subID, filters, nil
|
||||
}
|
||||
|
||||
// FindEOSE extracts subscription ID from an EOSE envelope.
|
||||
// Expected Format: ["EOSE", subID]
|
||||
func FindEOSE(env Envelope) (subID string, err error) {
|
||||
var arr []json.RawMessage
|
||||
if err = json.Unmarshal(env, &arr); err != nil {
|
||||
return "", fmt.Errorf("%w: %v", errors.InvalidJSON, err)
|
||||
}
|
||||
|
||||
if err = CheckArrayLength(arr, 2); err != nil {
|
||||
return "", err
|
||||
}
|
||||
|
||||
var label string
|
||||
if err := ParseElement(arr[0], &label, "envelope label"); err != nil {
|
||||
return "", err
|
||||
}
|
||||
|
||||
if err = CheckLabel(label, "EOSE"); err != nil {
|
||||
return "", err
|
||||
}
|
||||
|
||||
if err = ParseElement(arr[1], &subID, "subscription ID"); err != nil {
|
||||
return "", err
|
||||
}
|
||||
|
||||
return subID, nil
|
||||
}
|
||||
|
||||
// FindClose extracts subscription ID from a CLOSE envelope.
|
||||
// Expected Format: ["CLOSE", subID]
|
||||
func FindClose(env Envelope) (subID string, err error) {
|
||||
var arr []json.RawMessage
|
||||
if err = json.Unmarshal(env, &arr); err != nil {
|
||||
return "", fmt.Errorf("%w: %v", errors.InvalidJSON, err)
|
||||
}
|
||||
|
||||
if err = CheckArrayLength(arr, 2); err != nil {
|
||||
return "", err
|
||||
}
|
||||
|
||||
var label string
|
||||
if err := ParseElement(arr[0], &label, "envelope label"); err != nil {
|
||||
return "", err
|
||||
}
|
||||
|
||||
if err = CheckLabel(label, "CLOSE"); err != nil {
|
||||
return "", err
|
||||
}
|
||||
|
||||
if err = ParseElement(arr[1], &subID, "subscription ID"); err != nil {
|
||||
return "", err
|
||||
}
|
||||
|
||||
return subID, nil
|
||||
}
|
||||
|
||||
// FindClosed extracts subscription ID and message from a CLOSED envelope.
|
||||
// Expected Format: ["CLOSED", subID, message]
|
||||
func FindClosed(env Envelope) (subID string, message string, err error) {
|
||||
var arr []json.RawMessage
|
||||
if err = json.Unmarshal(env, &arr); err != nil {
|
||||
return "", "", fmt.Errorf("%w: %v", errors.InvalidJSON, err)
|
||||
}
|
||||
|
||||
if err = CheckArrayLength(arr, 3); err != nil {
|
||||
return "", "", err
|
||||
}
|
||||
|
||||
var label string
|
||||
if err := ParseElement(arr[0], &label, "envelope label"); err != nil {
|
||||
return "", "", err
|
||||
}
|
||||
|
||||
if err = CheckLabel(label, "CLOSED"); err != nil {
|
||||
return "", "", err
|
||||
}
|
||||
|
||||
if err = ParseElement(arr[1], &subID, "subscription ID"); err != nil {
|
||||
return "", "", err
|
||||
}
|
||||
|
||||
if err = ParseElement(arr[2], &message, "message"); err != nil {
|
||||
return "", "", err
|
||||
}
|
||||
|
||||
return subID, message, nil
|
||||
}
|
||||
|
||||
// FindNotice extracts message from a NOTICE envelope.
|
||||
// Expected Format: ["NOTICE", message]
|
||||
func FindNotice(env Envelope) (message string, err error) {
|
||||
var arr []json.RawMessage
|
||||
if err = json.Unmarshal(env, &arr); err != nil {
|
||||
return "", fmt.Errorf("%w: %v", errors.InvalidJSON, err)
|
||||
}
|
||||
|
||||
if err = CheckArrayLength(arr, 2); err != nil {
|
||||
return "", err
|
||||
}
|
||||
|
||||
var label string
|
||||
if err := ParseElement(arr[0], &label, "envelope label"); err != nil {
|
||||
return "", err
|
||||
}
|
||||
|
||||
if err = CheckLabel(label, "NOTICE"); err != nil {
|
||||
return "", err
|
||||
}
|
||||
|
||||
if err = ParseElement(arr[1], &message, "message"); err != nil {
|
||||
return "", err
|
||||
}
|
||||
|
||||
return message, nil
|
||||
}
|
||||
|
||||
// FindAuthChallenge extracts challenge from an AUTH challenge envelope.
|
||||
// Expected Format: ["AUTH", challenge]
|
||||
func FindAuthChallenge(env Envelope) (challenge string, err error) {
|
||||
var arr []json.RawMessage
|
||||
if err = json.Unmarshal(env, &arr); err != nil {
|
||||
return "", fmt.Errorf("%w: %v", errors.InvalidJSON, err)
|
||||
}
|
||||
|
||||
if err = CheckArrayLength(arr, 2); err != nil {
|
||||
return "", err
|
||||
}
|
||||
|
||||
var label string
|
||||
if err := ParseElement(arr[0], &label, "envelope label"); err != nil {
|
||||
return "", err
|
||||
}
|
||||
|
||||
if err = CheckLabel(label, "AUTH"); err != nil {
|
||||
return "", err
|
||||
}
|
||||
|
||||
// Check if the second element is a string (AUTH challenge)
|
||||
if err = ParseElement(arr[1], &challenge, "challenge"); err != nil {
|
||||
return "", err
|
||||
}
|
||||
|
||||
return challenge, nil
|
||||
}
|
||||
|
||||
// FindAuthResponse extracts event from an AUTH response envelope.
|
||||
// Expected Format: ["AUTH", event]
|
||||
func FindAuthResponse(env Envelope) (event []byte, err error) {
|
||||
var arr []json.RawMessage
|
||||
if err = json.Unmarshal(env, &arr); err != nil {
|
||||
return nil, fmt.Errorf("%w: %v", errors.InvalidJSON, err)
|
||||
}
|
||||
|
||||
if err = CheckArrayLength(arr, 2); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
var label string
|
||||
if err := ParseElement(arr[0], &label, "envelope label"); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
if err = CheckLabel(label, "AUTH"); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
return arr[1], nil
|
||||
}
|
||||
Reference in New Issue
Block a user