Skip to content

Commit

Permalink
Merge pull request #16 from ivancorrales/14-request-provide-error-han…
Browse files Browse the repository at this point in the history
…dling

Provide function Error to check errors
  • Loading branch information
ivancorrales committed Aug 14, 2023
2 parents 4816588 + 548883a commit 5123da3
Show file tree
Hide file tree
Showing 8 changed files with 81 additions and 42 deletions.
2 changes: 1 addition & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -114,7 +114,7 @@ require (

### Pre-requisites

* Go 1.19+
* Go 1.20+

### Examples

Expand Down
9 changes: 4 additions & 5 deletions internal/normalizer.go
Original file line number Diff line number Diff line change
Expand Up @@ -15,21 +15,20 @@ func normalize[T Type](input T) any {
switch value.Kind() {
case reflect.Slice, reflect.Array:
itemsLen := value.Len()
if itemsLen == 0 {
return make([]any, 1)
}
output := make([]any, itemsLen)
for i := 0; i < itemsLen; i++ {
itemValue := reflect.ValueOf(input).Index(i).Interface()
output[i] = evalValue(itemValue)
}
if itemsLen == 0 {
output = make([]any, 1)
}
return output
case reflect.Struct:
return structs.Map(input)
case reflect.Map:
output := make(map[string]any)
in, ok := reflect.ValueOf(input).Interface().(map[string]any)
if ok {
if in, ok := reflect.ValueOf(input).Interface().(map[string]any); ok {
for k, v := range in {
output[k] = evalValue(v)
}
Expand Down
39 changes: 28 additions & 11 deletions knoa.go
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
package knoa

import (
"errors"
"fmt"
"reflect"

Expand Down Expand Up @@ -99,25 +100,41 @@ func (k *knoa[T]) With(opts ...mutator.OperationOpt) func(args ...any) Knoa[T] {
setter := mutator.NewOperation(opts...)
return func(args ...any) Knoa[T] {
pathValueList := sanitizer.SanitizePathValueList(k.strictMode, args...)
k.mutators = append(k.mutators, setter.Set(k.parser, pathValueList)...)
mutators, err := setter.Set(k.parser, pathValueList)
if err != nil {
k.err = errors.Join(k.err, err)
}
k.mutators = append(k.mutators, mutators...)
return k
}
}

func (k *knoa[T]) Set(args ...any) Knoa[T] {
pathValueList := sanitizer.SanitizePathValueList(k.strictMode, args...)
k.mutators = append(k.mutators, mutator.NewOperation().Set(k.parser, pathValueList)...)
mutators, err := mutator.NewOperation().Set(k.parser, pathValueList)
if err != nil {
k.err = errors.Join(k.err, err)
}
k.mutators = append(k.mutators, mutators...)
return k
}

func (k *knoa[T]) Unset(args ...string) Knoa[T] {
k.mutators = append(k.mutators, mutator.NewOperation().Unset(k.parser, args)...)
mutators, err := mutator.NewOperation().Unset(k.parser, args)
if err != nil {
k.err = errors.Join(k.err, err)
}
k.mutators = append(k.mutators, mutators...)
return k
}

func (k *knoa[T]) Apply(args ...any) Knoa[T] {
pathFuncList := sanitizer.SanitizePathFuncList(k.strictMode, args...)
k.mutators = append(k.mutators, mutator.NewOperation().Apply(k.parser, pathFuncList)...)
mutators, err := mutator.NewOperation().Apply(k.parser, pathFuncList)
if err != nil {
k.err = errors.Join(k.err, err)
}
k.mutators = append(k.mutators, mutators...)
return k
}

Expand All @@ -133,24 +150,24 @@ func (k *knoa[T]) Out() T {
}
arrayIn, err := m.Child().ToArray(in)
if err != nil {
k.err = err
k.err = errors.Join(k.err, err)
break
}
content, _ = reflect.ValueOf(arrayIn).Interface().(T)
case reflect.Map:
in, ok := reflect.ValueOf(content).Interface().(map[string]any)
if !ok {
k.err = fmt.Errorf("unsupported map type")
k.err = errors.Join(k.err, fmt.Errorf("unsupported map type"))
break
}
mapIn, err := m.Child().ToMap(in)
if err != nil {
k.err = err
k.err = errors.Join(k.err, err)
break
}
content, _ = reflect.ValueOf(mapIn).Interface().(T)
default:
k.err = fmt.Errorf("unsupporteed output type '%s'", reflect.TypeOf(content).Kind())
k.err = errors.Join(k.err, fmt.Errorf("unsupporteed output type '%s'", reflect.TypeOf(content).Kind()))
}
}
return content
Expand All @@ -159,20 +176,20 @@ func (k *knoa[T]) Out() T {
func (k *knoa[T]) YAML(opts ...outputter.YAMLOpt) string {
content := k.Out()
str, err := outputter.NewYAML(opts...).Marshal(content)
k.err = err
k.err = errors.Join(k.err, err)
return str
}

func (k *knoa[T]) JSON(opts ...outputter.JSONOpt) string {
content := k.Out()
str, err := outputter.NewJSON(opts...).Marshal(content)
k.err = err
k.err = errors.Join(k.err, err)
return str
}

func (k *knoa[T]) To(out interface{}) {
content := k.Out()
k.err = mapstructure.Decode(content, out)
k.err = errors.Join(k.err, mapstructure.Decode(content, out))
}

func (k *knoa[T]) Error() error {
Expand Down
24 changes: 17 additions & 7 deletions mutator/mutator.go
Original file line number Diff line number Diff line change
Expand Up @@ -88,32 +88,42 @@ func (m *Mutator) ToMap(content map[string]any) (map[string]any, error) {
}
mt := *m.Child()
c := content[m.name]
var ok bool
switch reflect.ValueOf(c).Kind() {
case reflect.Slice, reflect.Array:
var childContent []any
if c == nil {
childContent = make([]any, 0)
} else {
childContent, _ = c.([]any)
childContent, ok = c.([]any)
if !ok {
return content, fmt.Errorf("invalid array")
}
}
value, toArrayErr := mt.ToArray(childContent)
if toArrayErr != nil {
return nil, toArrayErr
}
content[m.name] = value
default:
if m.operation == unsetOp {
delete(content, m.name)
return content, nil
}
var childContent map[string]any
if c == nil {
childContent = make(map[string]any)
} else {
childContent, _ = c.(map[string]any)
childContent, ok = c.(map[string]any)
if !ok {
return content, fmt.Errorf("invalid array")
}
}
mt.ToMap(childContent)
if m.operation == unsetOp {
delete(content, m.name)
return content, nil
value, toMapErr := mt.ToMap(childContent)
if toMapErr != nil {
return nil, toMapErr
}
content[m.name] = childContent
content[m.name] = value
}

return content, nil
Expand Down
28 changes: 19 additions & 9 deletions mutator/operation.go
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
package mutator

import (
"errors"
"reflect"

"github.com/fatih/structs"
Expand Down Expand Up @@ -43,7 +44,7 @@ func NewOperation(opts ...OperationOpt) *operation {
return op
}

func (op *operation) Set(parser *Parser, pathValueList sanitizer.PathValueList) (mutators []Mutator) {
func (op *operation) Set(parser *Parser, pathValueList sanitizer.PathValueList) (mutators []Mutator, outErr error) {
for _, pathValue := range pathValueList {
v := op.checkValue(pathValue.Value)
path := pathValue.Path
Expand All @@ -53,33 +54,39 @@ func (op *operation) Set(parser *Parser, pathValueList sanitizer.PathValueList)
if op.funcPrefix != nil {
path = op.funcPrefix(path)
}
m := parser.Parse(path)
m, err := parser.Parse(path)
if err != nil {
outErr = errors.Join(outErr, err)
}
if m != nil {
m.addValueToNode(v)
mutators = append(mutators, *m)
}
}
return mutators
return
}

func (op *operation) Unset(parser *Parser, paths []string) (mutators []Mutator) {
func (op *operation) Unset(parser *Parser, paths []string) (mutators []Mutator, outErr error) {
for _, path := range paths {
if op.prefix != "" {
path = op.prefix + path
}
if op.funcPrefix != nil {
path = op.funcPrefix(path)
}
m := parser.Parse(path)
m, err := parser.Parse(path)
if err != nil {
outErr = errors.Join(outErr, err)
}
if m != nil {
m.operation = unsetOp
mutators = append(mutators, *m)
}
}
return mutators
return
}

func (op *operation) Apply(parser *Parser, patchFuncList sanitizer.PathFuncList) (mutators []Mutator) {
func (op *operation) Apply(parser *Parser, patchFuncList sanitizer.PathFuncList) (mutators []Mutator, outErr error) {
for _, pathFunc := range patchFuncList {
path := pathFunc.Path
if op.prefix != "" {
Expand All @@ -88,14 +95,17 @@ func (op *operation) Apply(parser *Parser, patchFuncList sanitizer.PathFuncList)
if op.funcPrefix != nil {
path = op.funcPrefix(path)
}
m := parser.Parse(path)
m, err := parser.Parse(path)
if err != nil {
outErr = errors.Join(outErr, err)
}
if m != nil {
m.operation = applyOp
m.addValueToNode(pathFunc.Func)
mutators = append(mutators, *m)
}
}
return mutators
return
}

func (op *operation) checkValue(value any) any {
Expand Down
18 changes: 10 additions & 8 deletions mutator/parser.go
Original file line number Diff line number Diff line change
Expand Up @@ -31,7 +31,7 @@ func RegExpsFromAttributeFormat(attributeFormat string) (*regexp.Regexp, *regexp
return regexp.MustCompile(regExpStr), regexp.MustCompile(fmt.Sprintf(`^(?P<attribute>%s)$`, attributeFormat))
}

func (p *Parser) Parse(pathExpr string) *Mutator {
func (p *Parser) Parse(pathExpr string) (*Mutator, error) {
match := p.RegExp.FindStringSubmatch(pathExpr)
if match == nil {
attrMatch := p.AttributeRegExp.FindStringSubmatch(pathExpr)
Expand All @@ -40,12 +40,12 @@ func (p *Parser) Parse(pathExpr string) *Mutator {
child: &Mutator{
name: pathExpr,
},
}
}, nil
}
if p.Strict {
log.Panicf("invalid Path '%v'. Path doesn't match defined format", pathExpr)
}
return nil
return nil, fmt.Errorf("invalid path '%s'", pathExpr)
}
subMatchMap := map[string]string{}
for i, name := range p.RegExp.SubexpNames() {
Expand All @@ -68,33 +68,35 @@ func (p *Parser) Parse(pathExpr string) *Mutator {
if arrayIndex != "" {
m.index = arrayIndex
parent := &Mutator{}
var err error
if parentExpr != "" {
parent = p.Parse(parentExpr)
parent, err = p.Parse(parentExpr)
if parent == nil {
parent = &Mutator{
name: parentExpr,
}
}
}
addToBottom(parent, m)
return parent
return parent, err
}
if parentExpr != "" {
if attr != "" {
if attr[0] == '"' && attr[len(attr)-1] == '"' {
m.name = attr[1 : len(attr)-1]
}
}
parent := p.Parse(parentExpr)
var err error
parent, err := p.Parse(parentExpr)
if parent == nil {
parent = &Mutator{
name: parentExpr,
}
}
addToBottom(parent, m)
return parent
return parent, err
}
return m
return m, nil
}

func addToBottom(parent *Mutator, child *Mutator) {
Expand Down
2 changes: 1 addition & 1 deletion mutator/parser_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -205,7 +205,7 @@ func Test_parser_parse(t *testing.T) {
if tt.panicked {
assert.Panics(t, func() { p.Parse(tt.args.pathExpr) }, "The execution should end panicking")
} else {
res := p.Parse(tt.args.pathExpr)
res, _ := p.Parse(tt.args.pathExpr)
assertParsedElements(t, tt.want, res)
}
})
Expand Down
1 change: 1 addition & 0 deletions playground/main.go
Original file line number Diff line number Diff line change
Expand Up @@ -76,4 +76,5 @@ func main() {
k.To(&person)
fmt.Println(person)
// {John 23 [{Bob 40 []}]}

}

0 comments on commit 5123da3

Please sign in to comment.