From cef5b8f117ce30aa90def02bf017789aa52c3220 Mon Sep 17 00:00:00 2001 From: cloneot Date: Fri, 30 Aug 2024 19:12:25 +0900 Subject: [PATCH] Refactor index validation in json array Delegate index validation to Get and Delete methods. GetObject, GetArray, GetText, GetCounter, GetTree return 'nil' for invalid index. InsertIntegerAfter, MoveAfterByIndex, SetInteger panic with "index out of bound" for invalid index. --- pkg/document/json/array.go | 60 +++++++++++++++++--------------------- 1 file changed, 27 insertions(+), 33 deletions(-) diff --git a/pkg/document/json/array.go b/pkg/document/json/array.go index 3cc713cd6..0b2013bf2 100644 --- a/pkg/document/json/array.go +++ b/pkg/document/json/array.go @@ -169,13 +169,22 @@ func (p *Array) MoveBefore(nextCreatedAt, createdAt *time.Ticket) { // MoveAfterByIndex moves the given element to its new position after the given previous element. func (p *Array) MoveAfterByIndex(prevIndex, targetIndex int) { - p.moveAfterInternal(p.Get(prevIndex).CreatedAt(), p.Get(targetIndex).CreatedAt()) + prev := p.Get(prevIndex) + target := p.Get(targetIndex) + if prev == nil || target == nil { + panic("index out of bound") + } + p.moveAfterInternal(prev.CreatedAt(), target.CreatedAt()) } // InsertIntegerAfter inserts the given integer after the given previous // element. func (p *Array) InsertIntegerAfter(index int, v int) *Array { - p.insertAfterInternal(p.Get(index).CreatedAt(), func(ticket *time.Ticket) crdt.Element { + prev := p.Get(index) + if prev == nil { + panic("index out of bound") + } + p.insertAfterInternal(prev.CreatedAt(), func(ticket *time.Ticket) crdt.Element { primitive, err := crdt.NewPrimitive(v, ticket) if err != nil { panic(err) @@ -202,15 +211,11 @@ func (p *Array) Get(idx int) crdt.Element { // GetObject returns Object of the given index. func (p *Array) GetObject(idx int) *Object { - if idx < 0 || p.Len() <= idx { + element := p.Get(idx) + if element == nil { return nil } - element, err := p.Array.Get(idx) - if err != nil { - panic(err) - } - switch elem := element.(type) { case *crdt.Object: return NewObject(p.context, elem) @@ -223,15 +228,11 @@ func (p *Array) GetObject(idx int) *Object { // GetArray returns Array of the given index. func (p *Array) GetArray(idx int) *Array { - if idx < 0 || p.Len() <= idx { + element := p.Get(idx) + if element == nil { return nil } - element, err := p.Array.Get(idx) - if err != nil { - panic(err) - } - switch elem := element.(type) { case *crdt.Array: return NewArray(p.context, elem) @@ -244,15 +245,11 @@ func (p *Array) GetArray(idx int) *Array { // GetText returns Text of the given index. func (p *Array) GetText(idx int) *Text { - if idx < 0 || p.Len() <= idx { + element := p.Get(idx) + if element == nil { return nil } - element, err := p.Array.Get(idx) - if err != nil { - panic(err) - } - switch elem := element.(type) { case *crdt.Text: text := NewText() @@ -266,15 +263,11 @@ func (p *Array) GetText(idx int) *Text { // GetCounter returns Counter of the given index. func (p *Array) GetCounter(idx int) *Counter { - if idx < 0 || p.Len() <= idx { + element := p.Get(idx) + if element == nil { return nil } - element, err := p.Array.Get(idx) - if err != nil { - panic(err) - } - switch elem := element.(type) { case *crdt.Counter: counter := NewCounter(elem.Value(), elem.ValueType()) @@ -288,15 +281,11 @@ func (p *Array) GetCounter(idx int) *Counter { // GetTree returns Tree of the given index. func (p *Array) GetTree(idx int) *Tree { - if idx < 0 || p.Len() <= idx { + element := p.Get(idx) + if element == nil { return nil } - element, err := p.Array.Get(idx) - if err != nil { - panic(err) - } - switch elem := element.(type) { case *crdt.Tree: tree := NewTree() @@ -310,7 +299,12 @@ func (p *Array) GetTree(idx int) *Tree { // SetInteger sets element of the given index. func (p *Array) SetInteger(idx int, value int) *Array { - p.setByIndexInternal(p.Get(idx).CreatedAt(), func(ticket *time.Ticket) crdt.Element { + target := p.Get(idx) + if target == nil { + panic("index out of bound") + } + + p.setByIndexInternal(target.CreatedAt(), func(ticket *time.Ticket) crdt.Element { primitive, err := crdt.NewPrimitive(value, ticket) if err != nil { panic(err)