Skip to content

Commit

Permalink
more cleanup and bug fixes
Browse files Browse the repository at this point in the history
  • Loading branch information
smrz2001 committed Jun 7, 2022
1 parent 0730ee1 commit c1d184f
Show file tree
Hide file tree
Showing 2 changed files with 54 additions and 16 deletions.
53 changes: 43 additions & 10 deletions traversal/amend/list.go
Original file line number Diff line number Diff line change
Expand Up @@ -194,28 +194,61 @@ func (a *listAmender) Add(path datamodel.Path, value datamodel.Node, createParen
atLeaf := remainingPath.Len() == 0
childIdx, err := childSeg.Index()
if err != nil {
return err
return datamodel.ErrInvalidSegmentForList{TroubleSegment: childSeg, Reason: err}
}
// Allow the index to be equal to the length - this just means that a new element needs to be added to the end of
// the list (i.e. appended).
if childIdx > a.Length() {
return datamodel.ErrNotExists{Segment: childSeg}
}
childVal, err := a.LookupBySegment(childSeg)
if err != nil {
// - Return any error other than "not exists".
// - If the chile node does not exist and `createParents = true`, create the new hierarchy, otherwise throw an
// error.
// - Even if `createParent = false`, if we're at the leaf, don't throw an error because we don't need to create
// any more intermediate parent nodes.
if _, notFoundErr := err.(datamodel.ErrNotExists); !notFoundErr || !(atLeaf || createParents) {
return err
}
}
// While building the nested amender tree, only count nodes as "added" when they didn't exist and had to be created
// to fill out the hierarchy.
// In the case of a list, also consider a node "added" if we're at the leaf. Even if there already was a child at
// that index, it just means we need to "insert" a new node at the index.
create := false
if (childVal == nil) || atLeaf {
create = true
}
var childKind datamodel.Kind
if atLeaf {
childVal = value
childKind = value.Kind()
} else if _, err := childSeg.Index(); err == nil {
// As per the discussion [here](https://github.com/smrz2001/go-ipld-prime/pull/1#issuecomment-1143035685), this
// code assumes that if we're dealing with an integral path segment, it corresponds to a list index.
childKind = datamodel.Kind_List
} else {
// From the same discussion as above, any non-integral, intermediate path can be assumed to be a map key.
childKind = datamodel.Kind_Map
// If we're not at the leaf yet, look ahead on the remaining path to determine what kind of intermediate parent
// node we need to create.
nextChildSeg, _ := remainingPath.Shift()
if _, err := nextChildSeg.Index(); err == nil {
// As per the discussion [here](https://github.com/smrz2001/go-ipld-prime/pull/1#issuecomment-1143035685),
// this code assumes that if we're dealing with an integral path segment, it corresponds to a list index.
childKind = datamodel.Kind_List
} else {
// From the same discussion as above, any non-integral, intermediate path can be assumed to be a map key.
childKind = datamodel.Kind_Map
}
}
// When adding to a list-amender we're *always* creating a new node, never "wrapping" an existing one. This is by
// virtue of list semantics, where an addition means inserting a new element, even if one already existed at the
// specified index.
childAmender := newAmender(value, a, childKind, true)
if atLeaf {
childAmender := newAmender(childVal, a, childKind, create)
if create {
a.mods.Insert(int(childIdx), listElement{int(childIdx), childAmender.(datamodel.Node)})
return nil
} else {
a.mods.Set(int(childIdx), listElement{int(childIdx), childAmender.(datamodel.Node)})
}
if atLeaf {
return nil
} else {
return childAmender.Add(remainingPath, value, createParents)
}
}
Expand Down
17 changes: 11 additions & 6 deletions traversal/amend/map.go
Original file line number Diff line number Diff line change
Expand Up @@ -260,13 +260,18 @@ func (a *mapAmender) Add(path datamodel.Path, value datamodel.Node, createParent
}
childVal = value
childKind = value.Kind()
} else if _, err := childSeg.Index(); err == nil {
// As per the discussion [here](https://github.com/smrz2001/go-ipld-prime/pull/1#issuecomment-1143035685), this
// code assumes that if we're dealing with an integral path segment, it corresponds to a list index.
childKind = datamodel.Kind_List
} else {
// From the same discussion as above, any non-integral, intermediate path can be assumed to be a map key.
childKind = datamodel.Kind_Map
// If we're not at the leaf yet, look ahead on the remaining path to determine what kind of intermediate parent
// node we need to create.
nextChildSeg, _ := remainingPath.Shift()
if _, err := nextChildSeg.Index(); err == nil {
// As per the discussion [here](https://github.com/smrz2001/go-ipld-prime/pull/1#issuecomment-1143035685),
// this code assumes that if we're dealing with an integral path segment, it corresponds to a list index.
childKind = datamodel.Kind_List
} else {
// From the same discussion as above, any non-integral, intermediate path can be assumed to be a map key.
childKind = datamodel.Kind_Map
}
}
childAmender := newAmender(childVal, a, childKind, create)
a.mods.Put(childSeg, childAmender)
Expand Down

0 comments on commit c1d184f

Please sign in to comment.