diff options
Diffstat (limited to 'internal/tree/mutations.go')
-rw-r--r-- | internal/tree/mutations.go | 48 |
1 files changed, 37 insertions, 11 deletions
diff --git a/internal/tree/mutations.go b/internal/tree/mutations.go index ec80ebd..9aa9056 100644 --- a/internal/tree/mutations.go +++ b/internal/tree/mutations.go @@ -3,11 +3,13 @@ package tree import ( "context" "fmt" + "strings" "go.neonxp.dev/djson/internal/model" + json "go.neonxp.dev/json/model" ) -func (t *Engine) Mutation(ctx context.Context, mut *model.Mutation) error { +func (t *stdCore) Mutation(ctx context.Context, mut *model.Mutation) error { t.mu.Lock() defer t.mu.Unlock() if err := t.execute(mut); err != nil { @@ -16,45 +18,69 @@ func (t *Engine) Mutation(ctx context.Context, mut *model.Mutation) error { return t.storage.Commit(ctx, *mut) } -func (t *Engine) execute(mut *model.Mutation) error { +func (t *stdCore) execute(mut *model.Mutation) error { switch mut.Type { case model.Create: if len(mut.Path) == 0 { // create root node - t.Root = mut.Body + inObject, ok := mut.Body.(*json.ObjectNode) + if !ok { + return fmt.Errorf("root node must be object") + } + t.Root = *inObject return nil } key := mut.Path[len(mut.Path)-1] path := mut.Path[:len(mut.Path)-1] - target, err := t.Root.Query(path) + target, err := json.Query(&t.Root, path) if err != nil { return err } - return target.Set(key, mut.Body) + targetObject, ok := target.(*json.ObjectNode) + if !ok { + return fmt.Errorf("node %s is not object", strings.Join(path, "/")) + } + return targetObject.Value.Set(key, mut.Body) case model.Merge: + inObject, ok := mut.Body.(*json.ObjectNode) + if !ok { + return fmt.Errorf("patch allowed only for objects") + } if len(mut.Path) == 0 { // patch root node - return t.Root.Merge(&mut.Body) + t.Root.Merge(inObject) + return nil } - target, err := t.Root.Query(mut.Path) + target, err := json.Query(&t.Root, mut.Path) if err != nil { return err } - return target.Merge(&mut.Body) + targetObject, ok := target.(*json.ObjectNode) + if !ok { + return fmt.Errorf("patch allowed only for objects") + } + targetObject.Merge(inObject) + return nil case model.Remove: if len(mut.Path) == 0 { return fmt.Errorf("can't remove root node. Only replace or create avaliable") } key := mut.Path[len(mut.Path)-1] if len(mut.Path) == 1 { - return t.Root.Remove(key) + t.Root.Remove(key) + return nil } path := mut.Path[:len(mut.Path)-1] - target, err := t.Root.Query(path) + target, err := json.Query(&t.Root, path) if err != nil { return err } - return target.Remove(key) + targetObject, ok := target.(*json.ObjectNode) + if !ok { + return fmt.Errorf("remove allowed only from objects") + } + targetObject.Remove(key) + return nil } return fmt.Errorf("invalid command type: %d", mut.Type) } |