Skip to content

Commit

Permalink
fix(list, table): add tests and fix bugs that came out of tests
Browse files Browse the repository at this point in the history
  • Loading branch information
vitoke committed Jul 5, 2021
1 parent 48bb82d commit c32a62d
Show file tree
Hide file tree
Showing 9 changed files with 629 additions and 361 deletions.
26 changes: 18 additions & 8 deletions deno_dist/list/implementation/leaf/non-empty.ts
Original file line number Diff line number Diff line change
Expand Up @@ -933,24 +933,34 @@ export class LeafTree<T>
_normalize(): List.NonEmpty<T> {
if (null !== this.middle) {
if (this.left.length + this.middle.length <= this.context.maxBlockSize) {
// first middle child can be merged with left
const result = this.middle.dropFirst();
const block = result[1];
return this.copy(this.left.concatChildren(block), undefined, null);
}
if (this.right.length + this.middle.length <= this.context.maxBlockSize) {
const result = this.middle.dropFirst();
// last middle child can be merged with right
const result = this.middle.dropLast();
const block = result[1];
return this.copy(undefined, block.concatChildren(this.right), null);
}
}
if (this.length > this.context.maxBlockSize) return this;
if (null === this.middle) return this.left.concatChildren(this.right);

if (this.length > this.context.maxBlockSize) {
// no option to merge
return this;
}

if (null === this.middle) {
// can merge left and right
return this.left.concatChildren(this.right);
}

if (this.context.isNonLeafBlock(this.middle)) {
const children = this.left.children.concat(
this.middle.getChild(0).children,
this.right.children
);
return this.left.copy(children);
// left, middle, and right can be merged into one block
return this.left
.concatChildren(this.middle.getChild(0))
.concatChildren(this.right);
}

RimbuError.throwInvalidStateError();
Expand Down
13 changes: 13 additions & 0 deletions deno_dist/list/implementation/tree/operations.ts
Original file line number Diff line number Diff line change
Expand Up @@ -110,6 +110,19 @@ export function treePrepend<
}

if (null === tree.middle && tree.right.canAddChild) {
if (tree.context.isReversedLeafBlock<any>(tree.left)) {
const newLeftChildren = Arr.splice(tree.left.children, 0, 1);
newLeftChildren.push(child);
const moveRightChild = tree.left.children[0];
const newLeftLength =
tree.left.length -
tree.getChildLength(moveRightChild) +
tree.getChildLength(child);
const newLeft = tree.left.copy(newLeftChildren, newLeftLength);
const newRight = tree.right.prependInternal(moveRightChild);
return tree.copy(newLeft, newRight);
}

const newLeftChildren = Arr.splice(
tree.left.children,
tree.context.maxBlockSize - 1,
Expand Down
7 changes: 7 additions & 0 deletions deno_dist/table/implementation/base.ts
Original file line number Diff line number Diff line change
Expand Up @@ -760,6 +760,8 @@ export class TableBuilder<

if (!changed) return none;

this._size++;

return columnBuilder;
};
}
Expand All @@ -769,7 +771,12 @@ export class TableBuilder<
columnBuilder,
remove
): RMap.Builder<C, V> | typeof remove => {
const preSize = columnBuilder.size;

changed = columnBuilder.modifyAt(column, options);

this._size += columnBuilder.size - preSize;

if (columnBuilder.isEmpty) return remove;
return columnBuilder;
};
Expand Down
26 changes: 18 additions & 8 deletions packages/list/src/implementation/leaf/non-empty.ts
Original file line number Diff line number Diff line change
Expand Up @@ -933,24 +933,34 @@ export class LeafTree<T>
_normalize(): List.NonEmpty<T> {
if (null !== this.middle) {
if (this.left.length + this.middle.length <= this.context.maxBlockSize) {
// first middle child can be merged with left
const result = this.middle.dropFirst();
const block = result[1];
return this.copy(this.left.concatChildren(block), undefined, null);
}
if (this.right.length + this.middle.length <= this.context.maxBlockSize) {
const result = this.middle.dropFirst();
// last middle child can be merged with right
const result = this.middle.dropLast();
const block = result[1];
return this.copy(undefined, block.concatChildren(this.right), null);
}
}
if (this.length > this.context.maxBlockSize) return this;
if (null === this.middle) return this.left.concatChildren(this.right);

if (this.length > this.context.maxBlockSize) {
// no option to merge
return this;
}

if (null === this.middle) {
// can merge left and right
return this.left.concatChildren(this.right);
}

if (this.context.isNonLeafBlock(this.middle)) {
const children = this.left.children.concat(
this.middle.getChild(0).children,
this.right.children
);
return this.left.copy(children);
// left, middle, and right can be merged into one block
return this.left
.concatChildren(this.middle.getChild(0))
.concatChildren(this.right);
}

RimbuError.throwInvalidStateError();
Expand Down
13 changes: 13 additions & 0 deletions packages/list/src/implementation/tree/operations.ts
Original file line number Diff line number Diff line change
Expand Up @@ -110,6 +110,19 @@ export function treePrepend<
}

if (null === tree.middle && tree.right.canAddChild) {
if (tree.context.isReversedLeafBlock<any>(tree.left)) {
const newLeftChildren = Arr.splice(tree.left.children, 0, 1);
newLeftChildren.push(child);
const moveRightChild = tree.left.children[0];
const newLeftLength =
tree.left.length -
tree.getChildLength(moveRightChild) +
tree.getChildLength(child);
const newLeft = tree.left.copy(newLeftChildren, newLeftLength);
const newRight = tree.right.prependInternal(moveRightChild);
return tree.copy(newLeft, newRight);
}

const newLeftChildren = Arr.splice(
tree.left.children,
tree.context.maxBlockSize - 1,
Expand Down
2 changes: 2 additions & 0 deletions packages/list/test/leaf-block.test.ts
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
import { Stream } from '@rimbu/stream';
import { ListContext, LeafBlock, LeafTree } from '../src/list-custom';

describe('LeafBlock', () => {
Expand Down Expand Up @@ -435,6 +436,7 @@ function runLeafBlockTests(
it('streamRange', () => {
const b5 = createBlock(1, 2, 3, 4, 5);

expect(b5.streamRange({ amount: 0 })).toBe(Stream.empty());
expect(b5.streamRange({ amount: 2 }).toArray()).toEqual([1, 2]);
expect(b5.streamRange({ amount: 2 }, true).toArray()).toEqual([2, 1]);

Expand Down
Loading

0 comments on commit c32a62d

Please sign in to comment.