diff --git a/cell/src/main/java/org/ton/java/cell/BinTree.java b/cell/src/main/java/org/ton/java/cell/BinTree.java index b55aeeed..1839f1d8 100644 --- a/cell/src/main/java/org/ton/java/cell/BinTree.java +++ b/cell/src/main/java/org/ton/java/cell/BinTree.java @@ -5,6 +5,8 @@ import java.util.Deque; import java.util.List; +import static java.util.Objects.isNull; + public class BinTree { ShardDescr value; BinTree left; @@ -37,65 +39,50 @@ private static BinTree buildTree(Deque cells) { } public Cell toCell() { - return toCellHelper(this); - } - - private Cell toCellHelper(BinTree node) { - if (node == null || node.value == null) { + if (this.value == null && this.left == null && this.right == null) { return CellBuilder.beginCell().endCell(); } - - CellBuilder cb = CellBuilder.beginCell(); - cb.storeBit(true); - cb.storeRef(CellBuilder.beginCell() - .storeBit(false) - .storeCell(node.value.toCell()) - .endCell()); - - if (node.left != null || node.right != null) { - cb.storeRef(addToBinTree(node.left, node.right)); - } - - return cb.endCell(); + List listView = this.toList(); + return addToBinTree(listView, null); } - private Cell addToBinTree(BinTree left, BinTree right) { - if (right != null) { + private static Cell addToBinTree(List cells, Cell left) { + if (!cells.isEmpty()) { CellBuilder cb = CellBuilder.beginCell(); cb.storeBit(true); cb.storeRef(CellBuilder.beginCell() .storeBit(false) - .storeCell(left != null ? toCellHelper(left) : CellBuilder.beginCell().endCell()) + .storeCell(isNull(left) ? cells.remove(0).toCell() : left) .endCell()); - cb.storeRef(toCellHelper(right)); + if (!cells.isEmpty()) { + cb.storeRef(addToBinTree(cells, cells.remove(0).toCell())); + } return cb.endCell(); } else { CellBuilder cb = CellBuilder.beginCell(); - cb.storeCell(left != null ? toCellHelper(left) : CellBuilder.beginCell().endCell()); + cb.storeBit(false); + cb.storeCell(left); return cb.endCell(); } } public static BinTree deserialize(CellSlice cs) { - if (cs.bits.getLength() == 0 || cs.isExotic()) { + if (cs.isExotic() || cs.bits.getLength() == 0) { return null; } - if (cs.loadBit()) { - BinTree left = null; - BinTree right = null; - + BinTree root = new BinTree(); + if (cs.loadBit() || !cs.refs.isEmpty()) { if (!cs.refs.isEmpty()) { - left = deserialize(CellSlice.beginParse(cs.loadRef())); + root.left = deserialize(CellSlice.beginParse(cs.loadRef())); } if (!cs.refs.isEmpty()) { - right = deserialize(CellSlice.beginParse(cs.loadRef())); + root.right = deserialize(CellSlice.beginParse(cs.loadRef())); } - - return new BinTree(null, left, right); + return root; } else { - ShardDescr value = ShardDescr.deserialize(cs); - return new BinTree(value); + root.value = ShardDescr.deserialize(cs); + return root; } } diff --git a/cell/src/test/java/org/ton/java/hashmaps/TestBinTree.java b/cell/src/test/java/org/ton/java/hashmaps/TestBinTree.java index 6d588fe6..2424a99c 100644 --- a/cell/src/test/java/org/ton/java/hashmaps/TestBinTree.java +++ b/cell/src/test/java/org/ton/java/hashmaps/TestBinTree.java @@ -55,6 +55,10 @@ private ShardDescr createShardDescr(int seqno) { .build(); } + private void printLog(Object o) { + log.info("ShardDescr: {}", o); + } + @Test public void testBinTreeDeque() { ShardDescr shardDescr1 = createShardDescr(1); @@ -75,7 +79,7 @@ public void testBinTreeDeque() { List bt = BinTree.deserialize(CellSlice.beginParse(c)).toList(); for (ShardDescr cc : bt) { - log.info("ShardDescr: {}", cc); + printLog(cc); } assertThat(bt.size()).isEqualTo(5); @@ -88,6 +92,23 @@ public void testBinTree() { ShardDescr shardDescr3 = createShardDescr(3); ShardDescr shardDescr4 = createShardDescr(4); ShardDescr shardDescr5 = createShardDescr(5); + ShardDescr shardDescr6 = createShardDescr(6); + ShardDescr shardDescr7 = createShardDescr(7); + ShardDescr shardDescr8 = createShardDescr(8); + ShardDescr shardDescr9 = createShardDescr(9); + ShardDescr shardDescr10 = createShardDescr(10); + + BinTree tree10 = new BinTree(shardDescr10); + BinTree tree9 = new BinTree(shardDescr9, tree10, null); + BinTree tree8 = new BinTree(shardDescr8); + BinTree tree7 = new BinTree(shardDescr7, tree8, tree9); + BinTree tree6 = new BinTree(shardDescr6); + BinTree tree5 = new BinTree(shardDescr5, tree6, tree7); + BinTree tree4 = new BinTree(shardDescr4, null, tree5); + BinTree tree3 = new BinTree(shardDescr3); + BinTree tree2 = new BinTree(shardDescr2, tree3, null); + + BinTree root = new BinTree(shardDescr1, tree2, tree4); Deque cells = new ArrayDeque<>(); cells.add(shardDescr1); @@ -95,28 +116,39 @@ public void testBinTree() { cells.add(shardDescr3); cells.add(shardDescr4); cells.add(shardDescr5); + cells.add(shardDescr6); + cells.add(shardDescr7); + cells.add(shardDescr8); + cells.add(shardDescr9); + cells.add(shardDescr10); - Cell c = BinTree.fromDeque(cells).toCell(); - - log.info("ShardDescr: {}", c); + Cell cRootFromDeque = BinTree.fromDeque(cells).toCell(); + Cell cRoot = root.toCell(); - BinTree tree = BinTree.deserialize(CellSlice.beginParse(c)); + BinTree tree = BinTree.deserialize(CellSlice.beginParse(cRootFromDeque)); + BinTree rootFromCell = BinTree.deserialize(CellSlice.beginParse(cRoot)); assertThat(tree).isNotNull(); + assertThat(root).isNotNull(); List deserializedTree = tree.toList(); - for (ShardDescr cc : tree.toList()) { - log.info("ShardDescr: {}", cc); + List deserializedRoot = rootFromCell.toList(); + for (int i = 0; i < 10; i++) { + assertThat(deserializedRoot.get(i).getSeqNo()).isEqualTo(deserializedTree.get(i).getSeqNo()); + printLog(deserializedTree.get(i)); } - assertThat(deserializedTree.size()).isEqualTo(5); + assertThat(deserializedTree.size()).isEqualTo(10); + assertThat(deserializedRoot.size()).isEqualTo(10); } @Test public void testBinTreeEmpty() { Deque cells = new ArrayDeque<>(); BinTree tree = BinTree.fromDeque(cells); + BinTree root = new BinTree(); - assertThat(tree).isEqualTo(null); + assertThat(tree).isNull(); + assertThat(root).isNotNull(); } @@ -127,15 +159,20 @@ public void testBinTreeOne() { Deque cells = new ArrayDeque<>(); cells.add(shardDescr1); - Cell c = BinTree.fromDeque(cells).toCell(); + BinTree root = new BinTree(shardDescr1); - List bt = BinTree.deserialize(CellSlice.beginParse(c)).toList(); + Cell cTree = BinTree.fromDeque(cells).toCell(); + Cell cRoot = root.toCell(); - for (ShardDescr cc : bt) { - log.info("ShardDescr: {}", cc); + List deserializedTree = BinTree.deserialize(CellSlice.beginParse(cTree)).toList(); + List deserializedRoot = BinTree.deserialize(CellSlice.beginParse(cRoot)).toList(); + + for (ShardDescr cc : deserializedTree) { + printLog(cc); } - assertThat(bt.size()).isEqualTo(1); + assertThat(deserializedTree.size()).isEqualTo(1); + assertThat(deserializedRoot.size()).isEqualTo(1); } @Test @@ -147,15 +184,20 @@ public void testBinTreeTwo() { cells.add(shardDescr1); cells.add(shardDescr2); - Cell c = BinTree.fromDeque(cells).toCell(); + BinTree root = new BinTree(shardDescr1, new BinTree(shardDescr1), null); - List bt = BinTree.deserialize(CellSlice.beginParse(c)).toList(); + Cell cTree = BinTree.fromDeque(cells).toCell(); + Cell cRoot = root.toCell(); - for (ShardDescr cc : bt) { - log.info("ShardDescr: {}", cc); + List deserializedTree = BinTree.deserialize(CellSlice.beginParse(cTree)).toList(); + List deserializedRoot = BinTree.deserialize(CellSlice.beginParse(cRoot)).toList(); + + for (ShardDescr cc : deserializedTree) { + printLog(cc); } - assertThat(bt.size()).isEqualTo(2); + assertThat(deserializedTree.size()).isEqualTo(2); + assertThat(deserializedRoot.size()).isEqualTo(2); } @Test @@ -171,12 +213,12 @@ public void testBinTreeThree() { Cell c = BinTree.fromDeque(cells).toCell(); - log.info("ShardDescr: {}", c); + printLog(c); List bt = BinTree.deserialize(CellSlice.beginParse(c)).toList(); for (ShardDescr cc : bt) { - log.info("ShardDescr: {}", cc); + printLog(cc); } assertThat(bt.size()).isEqualTo(3);