formidable/internal/jsonpointer/pointer.go
2022-05-03 18:04:11 +02:00

93 lines
1.7 KiB
Go

package jsonpointer
import (
"strings"
"github.com/pkg/errors"
)
const (
TokenSeparator = "/"
NonExistentMemberToken = "-"
)
type Pointer struct {
tokens []string
}
func (p *Pointer) Get(doc interface{}) (interface{}, error) {
value, err := get(doc, p.tokens)
if err != nil {
return nil, errors.WithStack(err)
}
return value, nil
}
func (p *Pointer) Set(doc interface{}, value interface{}) (interface{}, error) {
doc, err := set(doc, p.tokens, value)
if err != nil {
return nil, errors.WithStack(err)
}
return doc, nil
}
func (p *Pointer) Force(doc interface{}, value interface{}) (interface{}, error) {
doc, err := force(doc, p.tokens, value)
if err != nil {
return nil, errors.WithStack(err)
}
return doc, nil
}
func (p *Pointer) Delete(doc interface{}) (interface{}, error) {
doc, err := del(doc, p.tokens)
if err != nil {
return nil, errors.WithStack(err)
}
return doc, nil
}
func New(raw string) *Pointer {
tokens := decodeTokens(raw)
return &Pointer{tokens}
}
func tokensToString(tokens []string) string {
escapedTokens := make([]string, 0)
for _, t := range tokens {
escapedTokens = append(escapedTokens, escapeToken(t))
}
return TokenSeparator + strings.Join(escapedTokens, TokenSeparator)
}
func escapeToken(token string) string {
token = strings.ReplaceAll(token, "/", "~1")
token = strings.ReplaceAll(token, "~", "~0")
return token
}
func unescapeToken(token string) string {
token = strings.ReplaceAll(token, "~1", "/")
token = strings.ReplaceAll(token, "~0", "~")
return token
}
func decodeTokens(raw string) []string {
tokens := strings.Split(raw, TokenSeparator)
for i, t := range tokens {
tokens[i] = unescapeToken(t)
}
return tokens[1:]
}