Mercurial > public > mercurial-scm > hg-stable
annotate rust/hg-core/src/revlog/nodemap.rs @ 45907:06b64fabf91c
copies: cache the ancestor checking call when tracing copy
A good share of the time spent in this function is spent doing ancestors
checking. To avoid spending time in duplicated call, we cache the result of
calls.
In the slower case, this provide a quite significant performance boost. Below
are the result for a set of selected pairs (many of them pathological):
(And further down is another table that summarize the current state of filelog
based vs changeset base copy tracing)
The benchmark have been configured to be killed after 6 minutes of runtime,
which mean that any detect slower than 2 minutes will be marked as "killed".
This drop some useful information about how much slower these case are? but also
prevent 99% of the benchmark time to be spent on case that can be labelled "very
slow" anyway.
Repo Case Source-Rev Dest-Rev Old-Time New-Time Difference Factor
------------------------------------------------------------------------------------------------------------------------------------
mercurial x_revs_x_added_0_copies ad6b123de1c7 39cfcef4f463 : 0.000044 s, 0.000044 s, +0.000000 s, ? 1.0000
mercurial x_revs_x_added_x_copies 2b1c78674230 0c1d10351869 : 0.000138 s, 0.000138 s, +0.000000 s, ? 1.0000
mercurial x000_revs_x000_added_x_copies 81f8ff2a9bf2 dd3267698d84 : 0.005067 s, 0.005052 s, -0.000015 s, ? 0.9970
pypy x_revs_x_added_0_copies aed021ee8ae8 099ed31b181b : 0.000218 s, 0.000219 s, +0.000001 s, ? 1.0046
pypy x_revs_x000_added_0_copies 4aa4e1f8e19a 359343b9ac0e : 0.000053 s, 0.000055 s, +0.000002 s, ? 1.0377
pypy x_revs_x_added_x_copies ac52eb7bbbb0 72e022663155 : 0.000125 s, 0.000128 s, +0.000003 s, ? 1.0240
pypy x_revs_x00_added_x_copies c3b14617fbd7 ace7255d9a26 : 0.001098 s, 0.001089 s, -0.000009 s, ? 0.9918
pypy x_revs_x000_added_x000_copies df6f7a526b60 a83dc6a2d56f : 0.017546 s, 0.017407 s, -0.000139 s, ? 0.9921
pypy x000_revs_xx00_added_0_copies 89a76aede314 2f22446ff07e : 0.096723 s, 0.094175 s, -0.002548 s, ? 0.9737
pypy x000_revs_x000_added_x_copies 8a3b5bfd266e 2c68e87c3efe : 0.271796 s, 0.238009 s, -0.033787 s, ? 0.8757
pypy x000_revs_x000_added_x000_copies 89a76aede314 7b3dda341c84 : 0.128602 s, 0.125876 s, -0.002726 s, ? 0.9788
pypy x0000_revs_x_added_0_copies d1defd0dc478 c9cb1334cc78 : 7.086742 s, 3.581556 s, -3.505186 s, ? 0.5054
pypy x0000_revs_xx000_added_0_copies bf2c629d0071 4ffed77c095c : 0.016634 s, 0.016721 s, +0.000087 s, ? 1.0052
pypy x0000_revs_xx000_added_x000_copies 08ea3258278e d9fa043f30c0 : 0.254225 s, 0.242367 s, -0.011858 s, ? 0.9534
netbeans x_revs_x_added_0_copies fb0955ffcbcd a01e9239f9e7 : 0.000166 s, 0.000165 s, -0.000001 s, ? 0.9940
netbeans x_revs_x000_added_0_copies 6f360122949f 20eb231cc7d0 : 0.000118 s, 0.000114 s, -0.000004 s, ? 0.9661
netbeans x_revs_x_added_x_copies 1ada3faf6fb6 5a39d12eecf4 : 0.000296 s, 0.000296 s, +0.000000 s, ? 1.0000
netbeans x_revs_x00_added_x_copies 35be93ba1e2c 9eec5e90c05f : 0.001137 s, 0.001124 s, -0.000013 s, ? 0.9886
netbeans x000_revs_xx00_added_0_copies eac3045b4fdd 51d4ae7f1290 : 0.014133 s, 0.013060 s, -0.001073 s, ? 0.9241
netbeans x000_revs_x000_added_x_copies e2063d266acd 6081d72689dc : 0.016988 s, 0.017112 s, +0.000124 s, ? 1.0073
netbeans x000_revs_x000_added_x000_copies ff453e9fee32 411350406ec2 : 0.676361 s, 0.660350 s, -0.016011 s, ? 0.9763
netbeans x0000_revs_xx000_added_x000_copies 588c2d1ced70 1aad62e59ddd : 12.515149 s, 10.032499 s, -2.482650 s, ? 0.8016
mozilla-central x_revs_x_added_0_copies 3697f962bb7b 7015fcdd43a2 : 0.000186 s, 0.000189 s, +0.000003 s, ? 1.0161
mozilla-central x_revs_x000_added_0_copies dd390860c6c9 40d0c5bed75d : 0.000459 s, 0.000462 s, +0.000003 s, ? 1.0065
mozilla-central x_revs_x_added_x_copies 8d198483ae3b 14207ffc2b2f : 0.000273 s, 0.000270 s, -0.000003 s, ? 0.9890
mozilla-central x_revs_x00_added_x_copies 98cbc58cc6bc 446a150332c3 : 0.001503 s, 0.001474 s, -0.000029 s, ? 0.9807
mozilla-central x_revs_x000_added_x000_copies 3c684b4b8f68 0a5e72d1b479 : 0.004862 s, 0.004806 s, -0.000056 s, ? 0.9885
mozilla-central x_revs_x0000_added_x0000_copies effb563bb7e5 c07a39dc4e80 : 0.088291 s, 0.085150 s, -0.003141 s, ? 0.9644
mozilla-central x000_revs_xx00_added_0_copies 6100d773079a 04a55431795e : 0.007113 s, 0.007064 s, -0.000049 s, ? 0.9931
mozilla-central x000_revs_x000_added_x_copies 9f17a6fc04f9 2d37b966abed : 0.004687 s, 0.004741 s, +0.000054 s, ? 1.0115
mozilla-central x000_revs_x000_added_x000_copies 7c97034feb78 4407bd0c6330 : 0.198710 s, 0.190133 s, -0.008577 s, ? 0.9568
mozilla-central x0000_revs_xx000_added_0_copies 9eec5917337d 67118cc6dcad : 0.036068 s, 0.035651 s, -0.000417 s, ? 0.9884
mozilla-central x0000_revs_xx000_added_x000_copies f78c615a656c 96a38b690156 : 0.465362 s, 0.440694 s, -0.024668 s, ? 0.9470
mozilla-central x00000_revs_x0000_added_x0000_copies 6832ae71433c 4c222a1d9a00 : 24.519684 s, 18.454163 s, -6.065521 s, ? 0.7526
mozilla-central x00000_revs_x00000_added_x000_copies 76caed42cf7c 1daa622bbe42 : 42.711897 s, 31.562719 s, -11.149178 s, ? 0.7390
mozilla-try x_revs_x_added_0_copies aaf6dde0deb8 9790f499805a : 0.001201 s, 0.001189 s, -0.000012 s, ? 0.9900
mozilla-try x_revs_x000_added_0_copies d8d0222927b4 5bb8ce8c7450 : 0.001216 s, 0.001204 s, -0.000012 s, ? 0.9901
mozilla-try x_revs_x_added_x_copies 092fcca11bdb 936255a0384a : 0.000595 s, 0.000586 s, -0.000009 s, ? 0.9849
mozilla-try x_revs_x00_added_x_copies b53d2fadbdb5 017afae788ec : 0.001856 s, 0.001845 s, -0.000011 s, ? 0.9941
mozilla-try x_revs_x000_added_x000_copies 20408ad61ce5 6f0ee96e21ad : 0.064936 s, 0.063822 s, -0.001114 s, ? 0.9828
mozilla-try x_revs_x0000_added_x0000_copies effb563bb7e5 c07a39dc4e80 : 0.090601 s, 0.088038 s, -0.002563 s, ? 0.9717
mozilla-try x000_revs_xx00_added_0_copies 6100d773079a 04a55431795e : 0.007510 s, 0.007389 s, -0.000121 s, ? 0.9839
mozilla-try x000_revs_x000_added_x_copies 9f17a6fc04f9 2d37b966abed : 0.004911 s, 0.004868 s, -0.000043 s, ? 0.9912
mozilla-try x000_revs_x000_added_x000_copies 1346fd0130e4 4c65cbdabc1f : 0.233231 s, 0.222450 s, -0.010781 s, ? 0.9538
mozilla-try x0000_revs_x_added_0_copies 63519bfd42ee a36a2a865d92 : 0.419989 s, 0.370675 s, -0.049314 s, ? 0.8826
mozilla-try x0000_revs_x_added_x_copies 9fe69ff0762d bcabf2a78927 : 0.401521 s, 0.358020 s, -0.043501 s, ? 0.8917
mozilla-try x0000_revs_xx000_added_x_copies 156f6e2674f2 4d0f2c178e66 : 0.179555 s, 0.145235 s, -0.034320 s, ? 0.8089
mozilla-try x0000_revs_xx000_added_0_copies 9eec5917337d 67118cc6dcad : 0.038004 s, 0.037606 s, -0.000398 s, ? 0.9895
mozilla-try x0000_revs_xx000_added_x000_copies 89294cd501d9 7ccb2fc7ccb5 : 52.838482 s, 7.382439 s, -45.456043 s, ? 0.1397
mozilla-try x0000_revs_x0000_added_x0000_copies e928c65095ed e951f4ad123a : 8.705874 s, 7.273506 s, -1.432368 s, ? 0.8355
mozilla-try x00000_revs_x00000_added_0_copies dc8a3ca7010e d16fde900c9c : 1.126708 s, 1.074593 s, -0.052115 s, ? 0.9537
mozilla-try x00000_revs_x0000_added_x0000_copies 8d3fafa80d4b eb884023b810 : 83.854020 s, 27.746195 s, -56.107825 s, ? 0.3309
Below is a table comparing the runtime of the current "filelog centric"
algorithm, with the "changeset centric" one, we just modified.
The changeset centric algorithm is a significant win in many scenario, but they
are still various cases where it is quite slower. When many revision has to be
considered the cost of retrieving the copy information, creating new
dictionaries, merging dictionaries and checking if revision are ancestors of
each other can slow things down.
The rest of this series, will introduce a rust version of the copy tracing code
to deal with most of theses issues.
Repo Case Source-Rev Dest-Rev filelog sidedata Difference Factor
---------------------------------------------------------------------------------------------------------------------------------------
mercurial x_revs_x_added_0_copies ad6b123de1c7 39cfcef4f463 : 0.000914 s, 0.000044 s, - 0.000870 s, ? 0.048140
mercurial x_revs_x_added_x_copies 2b1c78674230 0c1d10351869 : 0.001812 s, 0.000138 s, - 0.001674 s, ? 0.076159
mercurial x000_revs_x000_added_x_copies 81f8ff2a9bf2 dd3267698d84 : 0.017954 s, 0.005052 s, - 0.012902 s, ? 0.281386
pypy x_revs_x_added_0_copies aed021ee8ae8 099ed31b181b : 0.001509 s, 0.000219 s, - 0.001290 s, ? 0.145129
pypy x_revs_x000_added_0_copies 4aa4e1f8e19a 359343b9ac0e : 0.206881 s, 0.000055 s, - 0.206826 s, ? 0.000266
pypy x_revs_x_added_x_copies ac52eb7bbbb0 72e022663155 : 0.016951 s, 0.000128 s, - 0.016823 s, ? 0.007551
pypy x_revs_x00_added_x_copies c3b14617fbd7 ace7255d9a26 : 0.019096 s, 0.001089 s, - 0.018007 s, ? 0.057028
pypy x_revs_x000_added_x000_copies df6f7a526b60 a83dc6a2d56f : 0.762506 s, 0.017407 s, - 0.745099 s, ? 0.022829
pypy x000_revs_xx00_added_0_copies 89a76aede314 2f22446ff07e : 1.179211 s, 0.094175 s, - 1.085036 s, ? 0.079863
pypy x000_revs_x000_added_x_copies 8a3b5bfd266e 2c68e87c3efe : 1.249058 s, 0.238009 s, - 1.011049 s, ? 0.190551
pypy x000_revs_x000_added_x000_copies 89a76aede314 7b3dda341c84 : 1.614107 s, 0.125876 s, - 1.488231 s, ? 0.077985
pypy x0000_revs_x_added_0_copies d1defd0dc478 c9cb1334cc78 : 0.001064 s, 3.581556 s, + 3.580492 s, ? 3366.124060
pypy x0000_revs_xx000_added_0_copies bf2c629d0071 4ffed77c095c : 1.061275 s, 0.016721 s, - 1.044554 s, ? 0.015756
pypy x0000_revs_xx000_added_x000_copies 08ea3258278e d9fa043f30c0 : 1.341119 s, 0.242367 s, - 1.098752 s, ? 0.180720
netbeans x_revs_x_added_0_copies fb0955ffcbcd a01e9239f9e7 : 0.027803 s, 0.000165 s, - 0.027638 s, ? 0.005935
netbeans x_revs_x000_added_0_copies 6f360122949f 20eb231cc7d0 : 0.130014 s, 0.000114 s, - 0.129900 s, ? 0.000877
netbeans x_revs_x_added_x_copies 1ada3faf6fb6 5a39d12eecf4 : 0.024990 s, 0.000296 s, - 0.024694 s, ? 0.011845
netbeans x_revs_x00_added_x_copies 35be93ba1e2c 9eec5e90c05f : 0.052201 s, 0.001124 s, - 0.051077 s, ? 0.021532
netbeans x000_revs_xx00_added_0_copies eac3045b4fdd 51d4ae7f1290 : 0.037642 s, 0.013060 s, - 0.024582 s, ? 0.346953
netbeans x000_revs_x000_added_x_copies e2063d266acd 6081d72689dc : 0.197086 s, 0.017112 s, - 0.179974 s, ? 0.086825
netbeans x000_revs_x000_added_x000_copies ff453e9fee32 411350406ec2 : 0.935148 s, 0.660350 s, - 0.274798 s, ? 0.706145
netbeans x0000_revs_xx000_added_x000_copies 588c2d1ced70 1aad62e59ddd : 3.920674 s, 10.032499 s, + 6.111825 s, ? 2.558871
mozilla-central x_revs_x_added_0_copies 3697f962bb7b 7015fcdd43a2 : 0.024232 s, 0.000189 s, - 0.024043 s, ? 0.007800
mozilla-central x_revs_x000_added_0_copies dd390860c6c9 40d0c5bed75d : 0.141483 s, 0.000462 s, - 0.141021 s, ? 0.003265
mozilla-central x_revs_x_added_x_copies 8d198483ae3b 14207ffc2b2f : 0.025775 s, 0.000270 s, - 0.025505 s, ? 0.010475
mozilla-central x_revs_x00_added_x_copies 98cbc58cc6bc 446a150332c3 : 0.084922 s, 0.001474 s, - 0.083448 s, ? 0.017357
mozilla-central x_revs_x000_added_x000_copies 3c684b4b8f68 0a5e72d1b479 : 0.194784 s, 0.004806 s, - 0.189978 s, ? 0.024673
mozilla-central x_revs_x0000_added_x0000_copies effb563bb7e5 c07a39dc4e80 : 2.161103 s, 0.085150 s, - 2.075953 s, ? 0.039401
mozilla-central x000_revs_xx00_added_0_copies 6100d773079a 04a55431795e : 0.089347 s, 0.007064 s, - 0.082283 s, ? 0.079063
mozilla-central x000_revs_x000_added_x_copies 9f17a6fc04f9 2d37b966abed : 0.732171 s, 0.004741 s, - 0.727430 s, ? 0.006475
mozilla-central x000_revs_x000_added_x000_copies 7c97034feb78 4407bd0c6330 : 1.157287 s, 0.190133 s, - 0.967154 s, ? 0.164292
mozilla-central x0000_revs_xx000_added_0_copies 9eec5917337d 67118cc6dcad : 6.726568 s, 0.035651 s, - 6.690917 s, ? 0.005300
mozilla-central x0000_revs_xx000_added_x000_copies f78c615a656c 96a38b690156 : 3.266229 s, 0.440694 s, - 2.825535 s, ? 0.134924
mozilla-central x00000_revs_x0000_added_x0000_copies 6832ae71433c 4c222a1d9a00 : 15.860534 s, 18.454163 s, + 2.593629 s, ? 1.163527
mozilla-central x00000_revs_x00000_added_x000_copies 76caed42cf7c 1daa622bbe42 : 20.450475 s, 31.562719 s, +11.112244 s, ? 1.543373
mozilla-try x_revs_x_added_0_copies aaf6dde0deb8 9790f499805a : 0.080442 s, 0.001189 s, - 0.079253 s, ? 0.014781
mozilla-try x_revs_x000_added_0_copies d8d0222927b4 5bb8ce8c7450 : 0.497672 s, 0.001204 s, - 0.496468 s, ? 0.002419
mozilla-try x_revs_x_added_x_copies 092fcca11bdb 936255a0384a : 0.021183 s, 0.000586 s, - 0.020597 s, ? 0.027664
mozilla-try x_revs_x00_added_x_copies b53d2fadbdb5 017afae788ec : 0.230991 s, 0.001845 s, - 0.229146 s, ? 0.007987
mozilla-try x_revs_x000_added_x000_copies 20408ad61ce5 6f0ee96e21ad : 1.118461 s, 0.063822 s, - 1.054639 s, ? 0.057062
mozilla-try x_revs_x0000_added_x0000_copies effb563bb7e5 c07a39dc4e80 : 2.206083 s, 0.088038 s, - 2.118045 s, ? 0.039907
mozilla-try x000_revs_xx00_added_0_copies 6100d773079a 04a55431795e : 0.089404 s, 0.007389 s, - 0.082015 s, ? 0.082647
mozilla-try x000_revs_x000_added_x_copies 9f17a6fc04f9 2d37b966abed : 0.733043 s, 0.004868 s, - 0.728175 s, ? 0.006641
mozilla-try x000_revs_x000_added_x000_copies 1346fd0130e4 4c65cbdabc1f : 1.163367 s, 0.222450 s, - 0.940917 s, ? 0.191212
mozilla-try x0000_revs_x_added_0_copies 63519bfd42ee a36a2a865d92 : 0.085456 s, 0.370675 s, + 0.285219 s, ? 4.337612
mozilla-try x0000_revs_x_added_x_copies 9fe69ff0762d bcabf2a78927 : 0.083601 s, 0.358020 s, + 0.274419 s, ? 4.282485
mozilla-try x0000_revs_xx000_added_x_copies 156f6e2674f2 4d0f2c178e66 : 7.366614 s, 0.145235 s, - 7.221379 s, ? 0.019715
mozilla-try x0000_revs_xx000_added_0_copies 9eec5917337d 67118cc6dcad : 6.664464 s, 0.037606 s, - 6.626858 s, ? 0.005643
mozilla-try x0000_revs_xx000_added_x000_copies 89294cd501d9 7ccb2fc7ccb5 : 7.467836 s, 7.382439 s, - 0.085397 s, ? 0.988565
mozilla-try x0000_revs_x0000_added_x0000_copies e928c65095ed e951f4ad123a : 9.801294 s, 7.273506 s, - 2.527788 s, ? 0.742097
mozilla-try x00000_revs_x_added_0_copies 6a320851d377 1ebb79acd503 : 0.091886 s, killed
mozilla-try x00000_revs_x00000_added_0_copies dc8a3ca7010e d16fde900c9c : 26.491140 s, 1.074593 s, -25.416547 s, ? 0.040564
mozilla-try x00000_revs_x_added_x_copies 5173c4b6f97c 95d83ee7242d : 0.092863 s, killed
mozilla-try x00000_revs_x000_added_x_copies 9126823d0e9c ca82787bb23c : 0.226823 s, killed
mozilla-try x00000_revs_x0000_added_x0000_copies 8d3fafa80d4b eb884023b810 : 18.914630 s, 27.746195 s, + 8.831565 s, ? 1.466917
mozilla-try x00000_revs_x00000_added_x0000_copies 1b661134e2ca 1ae03d022d6d : 21.198903 s, killed
mozilla-try x00000_revs_x00000_added_x000_copies 9b2a99adc05e 8e29777b48e6 : 24.952268 s, killed
Differential Revision: https://phab.mercurial-scm.org/D9296
author | Pierre-Yves David <pierre-yves.david@octobus.net> |
---|---|
date | Mon, 02 Nov 2020 11:03:56 +0100 |
parents | 26114bd6ec60 |
children | 0800aa42bb4c |
rev | line source |
---|---|
44227
63db6657d280
rust-nodemap: building blocks for nodetree structures
Georges Racinet <georges.racinet@octobus.net>
parents:
diff
changeset
|
1 // Copyright 2018-2020 Georges Racinet <georges.racinet@octobus.net> |
63db6657d280
rust-nodemap: building blocks for nodetree structures
Georges Racinet <georges.racinet@octobus.net>
parents:
diff
changeset
|
2 // and Mercurial contributors |
63db6657d280
rust-nodemap: building blocks for nodetree structures
Georges Racinet <georges.racinet@octobus.net>
parents:
diff
changeset
|
3 // |
63db6657d280
rust-nodemap: building blocks for nodetree structures
Georges Racinet <georges.racinet@octobus.net>
parents:
diff
changeset
|
4 // This software may be used and distributed according to the terms of the |
63db6657d280
rust-nodemap: building blocks for nodetree structures
Georges Racinet <georges.racinet@octobus.net>
parents:
diff
changeset
|
5 // GNU General Public License version 2 or any later version. |
63db6657d280
rust-nodemap: building blocks for nodetree structures
Georges Racinet <georges.racinet@octobus.net>
parents:
diff
changeset
|
6 //! Indexing facilities for fast retrieval of `Revision` from `Node` |
63db6657d280
rust-nodemap: building blocks for nodetree structures
Georges Racinet <georges.racinet@octobus.net>
parents:
diff
changeset
|
7 //! |
63db6657d280
rust-nodemap: building blocks for nodetree structures
Georges Racinet <georges.racinet@octobus.net>
parents:
diff
changeset
|
8 //! This provides a variation on the 16-ary radix tree that is |
63db6657d280
rust-nodemap: building blocks for nodetree structures
Georges Racinet <georges.racinet@octobus.net>
parents:
diff
changeset
|
9 //! provided as "nodetree" in revlog.c, ready for append-only persistence |
63db6657d280
rust-nodemap: building blocks for nodetree structures
Georges Racinet <georges.racinet@octobus.net>
parents:
diff
changeset
|
10 //! on disk. |
63db6657d280
rust-nodemap: building blocks for nodetree structures
Georges Racinet <georges.racinet@octobus.net>
parents:
diff
changeset
|
11 //! |
63db6657d280
rust-nodemap: building blocks for nodetree structures
Georges Racinet <georges.racinet@octobus.net>
parents:
diff
changeset
|
12 //! Following existing implicit conventions, the "nodemap" terminology |
63db6657d280
rust-nodemap: building blocks for nodetree structures
Georges Racinet <georges.racinet@octobus.net>
parents:
diff
changeset
|
13 //! is used in a more abstract context. |
63db6657d280
rust-nodemap: building blocks for nodetree structures
Georges Racinet <georges.racinet@octobus.net>
parents:
diff
changeset
|
14 |
44258
e52401a95b94
rust-nodemap: NodeMap trait with simplest implementation
Georges Racinet <georges.racinet@octobus.net>
parents:
44227
diff
changeset
|
15 use super::{ |
44418
00d251d32007
rust-nodemap: special case for prefixes of NULL_NODE
Georges Racinet <georges.racinet@octobus.net>
parents:
44416
diff
changeset
|
16 node::NULL_NODE, Node, NodeError, NodePrefix, NodePrefixRef, Revision, |
00d251d32007
rust-nodemap: special case for prefixes of NULL_NODE
Georges Racinet <georges.racinet@octobus.net>
parents:
44416
diff
changeset
|
17 RevlogIndex, NULL_REVISION, |
44258
e52401a95b94
rust-nodemap: NodeMap trait with simplest implementation
Georges Racinet <georges.racinet@octobus.net>
parents:
44227
diff
changeset
|
18 }; |
44390
d2da8667125b
rust-nodemap: insert method
Georges Racinet <georges.racinet@octobus.net>
parents:
44261
diff
changeset
|
19 |
44419
5ac1eecc9c64
rust-nodemap: core implementation for shortest
Georges Racinet <georges.racinet@octobus.net>
parents:
44418
diff
changeset
|
20 use std::cmp::max; |
44227
63db6657d280
rust-nodemap: building blocks for nodetree structures
Georges Racinet <georges.racinet@octobus.net>
parents:
diff
changeset
|
21 use std::fmt; |
44416
a98ba6983a63
rust-nodemap: input/output primitives
Georges Racinet <georges.racinet@octobus.net>
parents:
44390
diff
changeset
|
22 use std::mem; |
44258
e52401a95b94
rust-nodemap: NodeMap trait with simplest implementation
Georges Racinet <georges.racinet@octobus.net>
parents:
44227
diff
changeset
|
23 use std::ops::Deref; |
44259
220d4d2e3185
rust-nodemap: abstracting the indexing
Georges Racinet <georges.racinet@octobus.net>
parents:
44258
diff
changeset
|
24 use std::ops::Index; |
44416
a98ba6983a63
rust-nodemap: input/output primitives
Georges Racinet <georges.racinet@octobus.net>
parents:
44390
diff
changeset
|
25 use std::slice; |
44258
e52401a95b94
rust-nodemap: NodeMap trait with simplest implementation
Georges Racinet <georges.racinet@octobus.net>
parents:
44227
diff
changeset
|
26 |
e52401a95b94
rust-nodemap: NodeMap trait with simplest implementation
Georges Racinet <georges.racinet@octobus.net>
parents:
44227
diff
changeset
|
27 #[derive(Debug, PartialEq)] |
e52401a95b94
rust-nodemap: NodeMap trait with simplest implementation
Georges Racinet <georges.racinet@octobus.net>
parents:
44227
diff
changeset
|
28 pub enum NodeMapError { |
e52401a95b94
rust-nodemap: NodeMap trait with simplest implementation
Georges Racinet <georges.racinet@octobus.net>
parents:
44227
diff
changeset
|
29 MultipleResults, |
e52401a95b94
rust-nodemap: NodeMap trait with simplest implementation
Georges Racinet <georges.racinet@octobus.net>
parents:
44227
diff
changeset
|
30 InvalidNodePrefix(NodeError), |
e52401a95b94
rust-nodemap: NodeMap trait with simplest implementation
Georges Racinet <georges.racinet@octobus.net>
parents:
44227
diff
changeset
|
31 /// A `Revision` stored in the nodemap could not be found in the index |
e52401a95b94
rust-nodemap: NodeMap trait with simplest implementation
Georges Racinet <georges.racinet@octobus.net>
parents:
44227
diff
changeset
|
32 RevisionNotInIndex(Revision), |
e52401a95b94
rust-nodemap: NodeMap trait with simplest implementation
Georges Racinet <georges.racinet@octobus.net>
parents:
44227
diff
changeset
|
33 } |
e52401a95b94
rust-nodemap: NodeMap trait with simplest implementation
Georges Racinet <georges.racinet@octobus.net>
parents:
44227
diff
changeset
|
34 |
e52401a95b94
rust-nodemap: NodeMap trait with simplest implementation
Georges Racinet <georges.racinet@octobus.net>
parents:
44227
diff
changeset
|
35 impl From<NodeError> for NodeMapError { |
e52401a95b94
rust-nodemap: NodeMap trait with simplest implementation
Georges Racinet <georges.racinet@octobus.net>
parents:
44227
diff
changeset
|
36 fn from(err: NodeError) -> Self { |
e52401a95b94
rust-nodemap: NodeMap trait with simplest implementation
Georges Racinet <georges.racinet@octobus.net>
parents:
44227
diff
changeset
|
37 NodeMapError::InvalidNodePrefix(err) |
e52401a95b94
rust-nodemap: NodeMap trait with simplest implementation
Georges Racinet <georges.racinet@octobus.net>
parents:
44227
diff
changeset
|
38 } |
e52401a95b94
rust-nodemap: NodeMap trait with simplest implementation
Georges Racinet <georges.racinet@octobus.net>
parents:
44227
diff
changeset
|
39 } |
e52401a95b94
rust-nodemap: NodeMap trait with simplest implementation
Georges Racinet <georges.racinet@octobus.net>
parents:
44227
diff
changeset
|
40 |
e52401a95b94
rust-nodemap: NodeMap trait with simplest implementation
Georges Racinet <georges.racinet@octobus.net>
parents:
44227
diff
changeset
|
41 /// Mapping system from Mercurial nodes to revision numbers. |
e52401a95b94
rust-nodemap: NodeMap trait with simplest implementation
Georges Racinet <georges.racinet@octobus.net>
parents:
44227
diff
changeset
|
42 /// |
e52401a95b94
rust-nodemap: NodeMap trait with simplest implementation
Georges Racinet <georges.racinet@octobus.net>
parents:
44227
diff
changeset
|
43 /// ## `RevlogIndex` and `NodeMap` |
e52401a95b94
rust-nodemap: NodeMap trait with simplest implementation
Georges Racinet <georges.racinet@octobus.net>
parents:
44227
diff
changeset
|
44 /// |
e52401a95b94
rust-nodemap: NodeMap trait with simplest implementation
Georges Racinet <georges.racinet@octobus.net>
parents:
44227
diff
changeset
|
45 /// One way to think about their relationship is that |
e52401a95b94
rust-nodemap: NodeMap trait with simplest implementation
Georges Racinet <georges.racinet@octobus.net>
parents:
44227
diff
changeset
|
46 /// the `NodeMap` is a prefix-oriented reverse index of the `Node` information |
e52401a95b94
rust-nodemap: NodeMap trait with simplest implementation
Georges Racinet <georges.racinet@octobus.net>
parents:
44227
diff
changeset
|
47 /// carried by a [`RevlogIndex`]. |
e52401a95b94
rust-nodemap: NodeMap trait with simplest implementation
Georges Racinet <georges.racinet@octobus.net>
parents:
44227
diff
changeset
|
48 /// |
e52401a95b94
rust-nodemap: NodeMap trait with simplest implementation
Georges Racinet <georges.racinet@octobus.net>
parents:
44227
diff
changeset
|
49 /// Many of the methods in this trait take a `RevlogIndex` argument |
e52401a95b94
rust-nodemap: NodeMap trait with simplest implementation
Georges Racinet <georges.racinet@octobus.net>
parents:
44227
diff
changeset
|
50 /// which is used for validation of their results. This index must naturally |
e52401a95b94
rust-nodemap: NodeMap trait with simplest implementation
Georges Racinet <georges.racinet@octobus.net>
parents:
44227
diff
changeset
|
51 /// be the one the `NodeMap` is about, and it must be consistent. |
e52401a95b94
rust-nodemap: NodeMap trait with simplest implementation
Georges Racinet <georges.racinet@octobus.net>
parents:
44227
diff
changeset
|
52 /// |
e52401a95b94
rust-nodemap: NodeMap trait with simplest implementation
Georges Racinet <georges.racinet@octobus.net>
parents:
44227
diff
changeset
|
53 /// Notably, the `NodeMap` must not store |
e52401a95b94
rust-nodemap: NodeMap trait with simplest implementation
Georges Racinet <georges.racinet@octobus.net>
parents:
44227
diff
changeset
|
54 /// information about more `Revision` values than there are in the index. |
e52401a95b94
rust-nodemap: NodeMap trait with simplest implementation
Georges Racinet <georges.racinet@octobus.net>
parents:
44227
diff
changeset
|
55 /// In these methods, an encountered `Revision` is not in the index, a |
e52401a95b94
rust-nodemap: NodeMap trait with simplest implementation
Georges Racinet <georges.racinet@octobus.net>
parents:
44227
diff
changeset
|
56 /// [`RevisionNotInIndex`] error is returned. |
e52401a95b94
rust-nodemap: NodeMap trait with simplest implementation
Georges Racinet <georges.racinet@octobus.net>
parents:
44227
diff
changeset
|
57 /// |
e52401a95b94
rust-nodemap: NodeMap trait with simplest implementation
Georges Racinet <georges.racinet@octobus.net>
parents:
44227
diff
changeset
|
58 /// In insert operations, the rule is thus that the `NodeMap` must always |
e52401a95b94
rust-nodemap: NodeMap trait with simplest implementation
Georges Racinet <georges.racinet@octobus.net>
parents:
44227
diff
changeset
|
59 /// be updated after the `RevlogIndex` |
e52401a95b94
rust-nodemap: NodeMap trait with simplest implementation
Georges Racinet <georges.racinet@octobus.net>
parents:
44227
diff
changeset
|
60 /// be updated first, and the `NodeMap` second. |
e52401a95b94
rust-nodemap: NodeMap trait with simplest implementation
Georges Racinet <georges.racinet@octobus.net>
parents:
44227
diff
changeset
|
61 /// |
e52401a95b94
rust-nodemap: NodeMap trait with simplest implementation
Georges Racinet <georges.racinet@octobus.net>
parents:
44227
diff
changeset
|
62 /// [`RevisionNotInIndex`]: enum.NodeMapError.html#variant.RevisionNotInIndex |
e52401a95b94
rust-nodemap: NodeMap trait with simplest implementation
Georges Racinet <georges.racinet@octobus.net>
parents:
44227
diff
changeset
|
63 /// [`RevlogIndex`]: ../trait.RevlogIndex.html |
e52401a95b94
rust-nodemap: NodeMap trait with simplest implementation
Georges Racinet <georges.racinet@octobus.net>
parents:
44227
diff
changeset
|
64 pub trait NodeMap { |
e52401a95b94
rust-nodemap: NodeMap trait with simplest implementation
Georges Racinet <georges.racinet@octobus.net>
parents:
44227
diff
changeset
|
65 /// Find the unique `Revision` having the given `Node` |
e52401a95b94
rust-nodemap: NodeMap trait with simplest implementation
Georges Racinet <georges.racinet@octobus.net>
parents:
44227
diff
changeset
|
66 /// |
e52401a95b94
rust-nodemap: NodeMap trait with simplest implementation
Georges Racinet <georges.racinet@octobus.net>
parents:
44227
diff
changeset
|
67 /// If no Revision matches the given `Node`, `Ok(None)` is returned. |
e52401a95b94
rust-nodemap: NodeMap trait with simplest implementation
Georges Racinet <georges.racinet@octobus.net>
parents:
44227
diff
changeset
|
68 fn find_node( |
e52401a95b94
rust-nodemap: NodeMap trait with simplest implementation
Georges Racinet <georges.racinet@octobus.net>
parents:
44227
diff
changeset
|
69 &self, |
e52401a95b94
rust-nodemap: NodeMap trait with simplest implementation
Georges Racinet <georges.racinet@octobus.net>
parents:
44227
diff
changeset
|
70 index: &impl RevlogIndex, |
e52401a95b94
rust-nodemap: NodeMap trait with simplest implementation
Georges Racinet <georges.racinet@octobus.net>
parents:
44227
diff
changeset
|
71 node: &Node, |
e52401a95b94
rust-nodemap: NodeMap trait with simplest implementation
Georges Racinet <georges.racinet@octobus.net>
parents:
44227
diff
changeset
|
72 ) -> Result<Option<Revision>, NodeMapError> { |
e52401a95b94
rust-nodemap: NodeMap trait with simplest implementation
Georges Racinet <georges.racinet@octobus.net>
parents:
44227
diff
changeset
|
73 self.find_bin(index, node.into()) |
e52401a95b94
rust-nodemap: NodeMap trait with simplest implementation
Georges Racinet <georges.racinet@octobus.net>
parents:
44227
diff
changeset
|
74 } |
e52401a95b94
rust-nodemap: NodeMap trait with simplest implementation
Georges Racinet <georges.racinet@octobus.net>
parents:
44227
diff
changeset
|
75 |
e52401a95b94
rust-nodemap: NodeMap trait with simplest implementation
Georges Racinet <georges.racinet@octobus.net>
parents:
44227
diff
changeset
|
76 /// Find the unique Revision whose `Node` starts with a given binary prefix |
e52401a95b94
rust-nodemap: NodeMap trait with simplest implementation
Georges Racinet <georges.racinet@octobus.net>
parents:
44227
diff
changeset
|
77 /// |
e52401a95b94
rust-nodemap: NodeMap trait with simplest implementation
Georges Racinet <georges.racinet@octobus.net>
parents:
44227
diff
changeset
|
78 /// If no Revision matches the given prefix, `Ok(None)` is returned. |
e52401a95b94
rust-nodemap: NodeMap trait with simplest implementation
Georges Racinet <georges.racinet@octobus.net>
parents:
44227
diff
changeset
|
79 /// |
e52401a95b94
rust-nodemap: NodeMap trait with simplest implementation
Georges Racinet <georges.racinet@octobus.net>
parents:
44227
diff
changeset
|
80 /// If several Revisions match the given prefix, a [`MultipleResults`] |
e52401a95b94
rust-nodemap: NodeMap trait with simplest implementation
Georges Racinet <georges.racinet@octobus.net>
parents:
44227
diff
changeset
|
81 /// error is returned. |
e52401a95b94
rust-nodemap: NodeMap trait with simplest implementation
Georges Racinet <georges.racinet@octobus.net>
parents:
44227
diff
changeset
|
82 fn find_bin<'a>( |
e52401a95b94
rust-nodemap: NodeMap trait with simplest implementation
Georges Racinet <georges.racinet@octobus.net>
parents:
44227
diff
changeset
|
83 &self, |
e52401a95b94
rust-nodemap: NodeMap trait with simplest implementation
Georges Racinet <georges.racinet@octobus.net>
parents:
44227
diff
changeset
|
84 idx: &impl RevlogIndex, |
e52401a95b94
rust-nodemap: NodeMap trait with simplest implementation
Georges Racinet <georges.racinet@octobus.net>
parents:
44227
diff
changeset
|
85 prefix: NodePrefixRef<'a>, |
e52401a95b94
rust-nodemap: NodeMap trait with simplest implementation
Georges Racinet <georges.racinet@octobus.net>
parents:
44227
diff
changeset
|
86 ) -> Result<Option<Revision>, NodeMapError>; |
e52401a95b94
rust-nodemap: NodeMap trait with simplest implementation
Georges Racinet <georges.racinet@octobus.net>
parents:
44227
diff
changeset
|
87 |
e52401a95b94
rust-nodemap: NodeMap trait with simplest implementation
Georges Racinet <georges.racinet@octobus.net>
parents:
44227
diff
changeset
|
88 /// Find the unique Revision whose `Node` hexadecimal string representation |
e52401a95b94
rust-nodemap: NodeMap trait with simplest implementation
Georges Racinet <georges.racinet@octobus.net>
parents:
44227
diff
changeset
|
89 /// starts with a given prefix |
e52401a95b94
rust-nodemap: NodeMap trait with simplest implementation
Georges Racinet <georges.racinet@octobus.net>
parents:
44227
diff
changeset
|
90 /// |
e52401a95b94
rust-nodemap: NodeMap trait with simplest implementation
Georges Racinet <georges.racinet@octobus.net>
parents:
44227
diff
changeset
|
91 /// If no Revision matches the given prefix, `Ok(None)` is returned. |
e52401a95b94
rust-nodemap: NodeMap trait with simplest implementation
Georges Racinet <georges.racinet@octobus.net>
parents:
44227
diff
changeset
|
92 /// |
e52401a95b94
rust-nodemap: NodeMap trait with simplest implementation
Georges Racinet <georges.racinet@octobus.net>
parents:
44227
diff
changeset
|
93 /// If several Revisions match the given prefix, a [`MultipleResults`] |
e52401a95b94
rust-nodemap: NodeMap trait with simplest implementation
Georges Racinet <georges.racinet@octobus.net>
parents:
44227
diff
changeset
|
94 /// error is returned. |
e52401a95b94
rust-nodemap: NodeMap trait with simplest implementation
Georges Racinet <georges.racinet@octobus.net>
parents:
44227
diff
changeset
|
95 fn find_hex( |
e52401a95b94
rust-nodemap: NodeMap trait with simplest implementation
Georges Racinet <georges.racinet@octobus.net>
parents:
44227
diff
changeset
|
96 &self, |
e52401a95b94
rust-nodemap: NodeMap trait with simplest implementation
Georges Racinet <georges.racinet@octobus.net>
parents:
44227
diff
changeset
|
97 idx: &impl RevlogIndex, |
e52401a95b94
rust-nodemap: NodeMap trait with simplest implementation
Georges Racinet <georges.racinet@octobus.net>
parents:
44227
diff
changeset
|
98 prefix: &str, |
e52401a95b94
rust-nodemap: NodeMap trait with simplest implementation
Georges Racinet <georges.racinet@octobus.net>
parents:
44227
diff
changeset
|
99 ) -> Result<Option<Revision>, NodeMapError> { |
e52401a95b94
rust-nodemap: NodeMap trait with simplest implementation
Georges Racinet <georges.racinet@octobus.net>
parents:
44227
diff
changeset
|
100 self.find_bin(idx, NodePrefix::from_hex(prefix)?.borrow()) |
e52401a95b94
rust-nodemap: NodeMap trait with simplest implementation
Georges Racinet <georges.racinet@octobus.net>
parents:
44227
diff
changeset
|
101 } |
44419
5ac1eecc9c64
rust-nodemap: core implementation for shortest
Georges Racinet <georges.racinet@octobus.net>
parents:
44418
diff
changeset
|
102 |
5ac1eecc9c64
rust-nodemap: core implementation for shortest
Georges Racinet <georges.racinet@octobus.net>
parents:
44418
diff
changeset
|
103 /// Give the size of the shortest node prefix that determines |
5ac1eecc9c64
rust-nodemap: core implementation for shortest
Georges Racinet <georges.racinet@octobus.net>
parents:
44418
diff
changeset
|
104 /// the revision uniquely. |
5ac1eecc9c64
rust-nodemap: core implementation for shortest
Georges Racinet <georges.racinet@octobus.net>
parents:
44418
diff
changeset
|
105 /// |
5ac1eecc9c64
rust-nodemap: core implementation for shortest
Georges Racinet <georges.racinet@octobus.net>
parents:
44418
diff
changeset
|
106 /// From a binary node prefix, if it is matched in the node map, this |
5ac1eecc9c64
rust-nodemap: core implementation for shortest
Georges Racinet <georges.racinet@octobus.net>
parents:
44418
diff
changeset
|
107 /// returns the number of hexadecimal digits that would had sufficed |
5ac1eecc9c64
rust-nodemap: core implementation for shortest
Georges Racinet <georges.racinet@octobus.net>
parents:
44418
diff
changeset
|
108 /// to find the revision uniquely. |
5ac1eecc9c64
rust-nodemap: core implementation for shortest
Georges Racinet <georges.racinet@octobus.net>
parents:
44418
diff
changeset
|
109 /// |
5ac1eecc9c64
rust-nodemap: core implementation for shortest
Georges Racinet <georges.racinet@octobus.net>
parents:
44418
diff
changeset
|
110 /// Returns `None` if no `Revision` could be found for the prefix. |
5ac1eecc9c64
rust-nodemap: core implementation for shortest
Georges Racinet <georges.racinet@octobus.net>
parents:
44418
diff
changeset
|
111 /// |
5ac1eecc9c64
rust-nodemap: core implementation for shortest
Georges Racinet <georges.racinet@octobus.net>
parents:
44418
diff
changeset
|
112 /// If several Revisions match the given prefix, a [`MultipleResults`] |
5ac1eecc9c64
rust-nodemap: core implementation for shortest
Georges Racinet <georges.racinet@octobus.net>
parents:
44418
diff
changeset
|
113 /// error is returned. |
5ac1eecc9c64
rust-nodemap: core implementation for shortest
Georges Racinet <georges.racinet@octobus.net>
parents:
44418
diff
changeset
|
114 fn unique_prefix_len_bin<'a>( |
5ac1eecc9c64
rust-nodemap: core implementation for shortest
Georges Racinet <georges.racinet@octobus.net>
parents:
44418
diff
changeset
|
115 &self, |
5ac1eecc9c64
rust-nodemap: core implementation for shortest
Georges Racinet <georges.racinet@octobus.net>
parents:
44418
diff
changeset
|
116 idx: &impl RevlogIndex, |
5ac1eecc9c64
rust-nodemap: core implementation for shortest
Georges Racinet <georges.racinet@octobus.net>
parents:
44418
diff
changeset
|
117 node_prefix: NodePrefixRef<'a>, |
5ac1eecc9c64
rust-nodemap: core implementation for shortest
Georges Racinet <georges.racinet@octobus.net>
parents:
44418
diff
changeset
|
118 ) -> Result<Option<usize>, NodeMapError>; |
5ac1eecc9c64
rust-nodemap: core implementation for shortest
Georges Racinet <georges.racinet@octobus.net>
parents:
44418
diff
changeset
|
119 |
5ac1eecc9c64
rust-nodemap: core implementation for shortest
Georges Racinet <georges.racinet@octobus.net>
parents:
44418
diff
changeset
|
120 /// Same as `unique_prefix_len_bin`, with the hexadecimal representation |
5ac1eecc9c64
rust-nodemap: core implementation for shortest
Georges Racinet <georges.racinet@octobus.net>
parents:
44418
diff
changeset
|
121 /// of the prefix as input. |
5ac1eecc9c64
rust-nodemap: core implementation for shortest
Georges Racinet <georges.racinet@octobus.net>
parents:
44418
diff
changeset
|
122 fn unique_prefix_len_hex( |
5ac1eecc9c64
rust-nodemap: core implementation for shortest
Georges Racinet <georges.racinet@octobus.net>
parents:
44418
diff
changeset
|
123 &self, |
5ac1eecc9c64
rust-nodemap: core implementation for shortest
Georges Racinet <georges.racinet@octobus.net>
parents:
44418
diff
changeset
|
124 idx: &impl RevlogIndex, |
5ac1eecc9c64
rust-nodemap: core implementation for shortest
Georges Racinet <georges.racinet@octobus.net>
parents:
44418
diff
changeset
|
125 prefix: &str, |
5ac1eecc9c64
rust-nodemap: core implementation for shortest
Georges Racinet <georges.racinet@octobus.net>
parents:
44418
diff
changeset
|
126 ) -> Result<Option<usize>, NodeMapError> { |
5ac1eecc9c64
rust-nodemap: core implementation for shortest
Georges Racinet <georges.racinet@octobus.net>
parents:
44418
diff
changeset
|
127 self.unique_prefix_len_bin(idx, NodePrefix::from_hex(prefix)?.borrow()) |
5ac1eecc9c64
rust-nodemap: core implementation for shortest
Georges Racinet <georges.racinet@octobus.net>
parents:
44418
diff
changeset
|
128 } |
5ac1eecc9c64
rust-nodemap: core implementation for shortest
Georges Racinet <georges.racinet@octobus.net>
parents:
44418
diff
changeset
|
129 |
5ac1eecc9c64
rust-nodemap: core implementation for shortest
Georges Racinet <georges.racinet@octobus.net>
parents:
44418
diff
changeset
|
130 /// Same as `unique_prefix_len_bin`, with a full `Node` as input |
5ac1eecc9c64
rust-nodemap: core implementation for shortest
Georges Racinet <georges.racinet@octobus.net>
parents:
44418
diff
changeset
|
131 fn unique_prefix_len_node( |
5ac1eecc9c64
rust-nodemap: core implementation for shortest
Georges Racinet <georges.racinet@octobus.net>
parents:
44418
diff
changeset
|
132 &self, |
5ac1eecc9c64
rust-nodemap: core implementation for shortest
Georges Racinet <georges.racinet@octobus.net>
parents:
44418
diff
changeset
|
133 idx: &impl RevlogIndex, |
5ac1eecc9c64
rust-nodemap: core implementation for shortest
Georges Racinet <georges.racinet@octobus.net>
parents:
44418
diff
changeset
|
134 node: &Node, |
5ac1eecc9c64
rust-nodemap: core implementation for shortest
Georges Racinet <georges.racinet@octobus.net>
parents:
44418
diff
changeset
|
135 ) -> Result<Option<usize>, NodeMapError> { |
5ac1eecc9c64
rust-nodemap: core implementation for shortest
Georges Racinet <georges.racinet@octobus.net>
parents:
44418
diff
changeset
|
136 self.unique_prefix_len_bin(idx, node.into()) |
5ac1eecc9c64
rust-nodemap: core implementation for shortest
Georges Racinet <georges.racinet@octobus.net>
parents:
44418
diff
changeset
|
137 } |
44258
e52401a95b94
rust-nodemap: NodeMap trait with simplest implementation
Georges Racinet <georges.racinet@octobus.net>
parents:
44227
diff
changeset
|
138 } |
44227
63db6657d280
rust-nodemap: building blocks for nodetree structures
Georges Racinet <georges.racinet@octobus.net>
parents:
diff
changeset
|
139 |
44390
d2da8667125b
rust-nodemap: insert method
Georges Racinet <georges.racinet@octobus.net>
parents:
44261
diff
changeset
|
140 pub trait MutableNodeMap: NodeMap { |
d2da8667125b
rust-nodemap: insert method
Georges Racinet <georges.racinet@octobus.net>
parents:
44261
diff
changeset
|
141 fn insert<I: RevlogIndex>( |
d2da8667125b
rust-nodemap: insert method
Georges Racinet <georges.racinet@octobus.net>
parents:
44261
diff
changeset
|
142 &mut self, |
d2da8667125b
rust-nodemap: insert method
Georges Racinet <georges.racinet@octobus.net>
parents:
44261
diff
changeset
|
143 index: &I, |
d2da8667125b
rust-nodemap: insert method
Georges Racinet <georges.racinet@octobus.net>
parents:
44261
diff
changeset
|
144 node: &Node, |
d2da8667125b
rust-nodemap: insert method
Georges Racinet <georges.racinet@octobus.net>
parents:
44261
diff
changeset
|
145 rev: Revision, |
d2da8667125b
rust-nodemap: insert method
Georges Racinet <georges.racinet@octobus.net>
parents:
44261
diff
changeset
|
146 ) -> Result<(), NodeMapError>; |
d2da8667125b
rust-nodemap: insert method
Georges Racinet <georges.racinet@octobus.net>
parents:
44261
diff
changeset
|
147 } |
d2da8667125b
rust-nodemap: insert method
Georges Racinet <georges.racinet@octobus.net>
parents:
44261
diff
changeset
|
148 |
44227
63db6657d280
rust-nodemap: building blocks for nodetree structures
Georges Racinet <georges.racinet@octobus.net>
parents:
diff
changeset
|
149 /// Low level NodeTree [`Blocks`] elements |
63db6657d280
rust-nodemap: building blocks for nodetree structures
Georges Racinet <georges.racinet@octobus.net>
parents:
diff
changeset
|
150 /// |
63db6657d280
rust-nodemap: building blocks for nodetree structures
Georges Racinet <georges.racinet@octobus.net>
parents:
diff
changeset
|
151 /// These are exactly as for instance on persistent storage. |
63db6657d280
rust-nodemap: building blocks for nodetree structures
Georges Racinet <georges.racinet@octobus.net>
parents:
diff
changeset
|
152 type RawElement = i32; |
63db6657d280
rust-nodemap: building blocks for nodetree structures
Georges Racinet <georges.racinet@octobus.net>
parents:
diff
changeset
|
153 |
63db6657d280
rust-nodemap: building blocks for nodetree structures
Georges Racinet <georges.racinet@octobus.net>
parents:
diff
changeset
|
154 /// High level representation of values in NodeTree |
63db6657d280
rust-nodemap: building blocks for nodetree structures
Georges Racinet <georges.racinet@octobus.net>
parents:
diff
changeset
|
155 /// [`Blocks`](struct.Block.html) |
63db6657d280
rust-nodemap: building blocks for nodetree structures
Georges Racinet <georges.racinet@octobus.net>
parents:
diff
changeset
|
156 /// |
63db6657d280
rust-nodemap: building blocks for nodetree structures
Georges Racinet <georges.racinet@octobus.net>
parents:
diff
changeset
|
157 /// This is the high level representation that most algorithms should |
63db6657d280
rust-nodemap: building blocks for nodetree structures
Georges Racinet <georges.racinet@octobus.net>
parents:
diff
changeset
|
158 /// use. |
63db6657d280
rust-nodemap: building blocks for nodetree structures
Georges Racinet <georges.racinet@octobus.net>
parents:
diff
changeset
|
159 #[derive(Clone, Debug, Eq, PartialEq)] |
63db6657d280
rust-nodemap: building blocks for nodetree structures
Georges Racinet <georges.racinet@octobus.net>
parents:
diff
changeset
|
160 enum Element { |
63db6657d280
rust-nodemap: building blocks for nodetree structures
Georges Racinet <georges.racinet@octobus.net>
parents:
diff
changeset
|
161 Rev(Revision), |
63db6657d280
rust-nodemap: building blocks for nodetree structures
Georges Racinet <georges.racinet@octobus.net>
parents:
diff
changeset
|
162 Block(usize), |
63db6657d280
rust-nodemap: building blocks for nodetree structures
Georges Racinet <georges.racinet@octobus.net>
parents:
diff
changeset
|
163 None, |
63db6657d280
rust-nodemap: building blocks for nodetree structures
Georges Racinet <georges.racinet@octobus.net>
parents:
diff
changeset
|
164 } |
63db6657d280
rust-nodemap: building blocks for nodetree structures
Georges Racinet <georges.racinet@octobus.net>
parents:
diff
changeset
|
165 |
63db6657d280
rust-nodemap: building blocks for nodetree structures
Georges Racinet <georges.racinet@octobus.net>
parents:
diff
changeset
|
166 impl From<RawElement> for Element { |
63db6657d280
rust-nodemap: building blocks for nodetree structures
Georges Racinet <georges.racinet@octobus.net>
parents:
diff
changeset
|
167 /// Conversion from low level representation, after endianness conversion. |
63db6657d280
rust-nodemap: building blocks for nodetree structures
Georges Racinet <georges.racinet@octobus.net>
parents:
diff
changeset
|
168 /// |
63db6657d280
rust-nodemap: building blocks for nodetree structures
Georges Racinet <georges.racinet@octobus.net>
parents:
diff
changeset
|
169 /// See [`Block`](struct.Block.html) for explanation about the encoding. |
63db6657d280
rust-nodemap: building blocks for nodetree structures
Georges Racinet <georges.racinet@octobus.net>
parents:
diff
changeset
|
170 fn from(raw: RawElement) -> Element { |
63db6657d280
rust-nodemap: building blocks for nodetree structures
Georges Racinet <georges.racinet@octobus.net>
parents:
diff
changeset
|
171 if raw >= 0 { |
63db6657d280
rust-nodemap: building blocks for nodetree structures
Georges Racinet <georges.racinet@octobus.net>
parents:
diff
changeset
|
172 Element::Block(raw as usize) |
63db6657d280
rust-nodemap: building blocks for nodetree structures
Georges Racinet <georges.racinet@octobus.net>
parents:
diff
changeset
|
173 } else if raw == -1 { |
63db6657d280
rust-nodemap: building blocks for nodetree structures
Georges Racinet <georges.racinet@octobus.net>
parents:
diff
changeset
|
174 Element::None |
63db6657d280
rust-nodemap: building blocks for nodetree structures
Georges Racinet <georges.racinet@octobus.net>
parents:
diff
changeset
|
175 } else { |
63db6657d280
rust-nodemap: building blocks for nodetree structures
Georges Racinet <georges.racinet@octobus.net>
parents:
diff
changeset
|
176 Element::Rev(-raw - 2) |
63db6657d280
rust-nodemap: building blocks for nodetree structures
Georges Racinet <georges.racinet@octobus.net>
parents:
diff
changeset
|
177 } |
63db6657d280
rust-nodemap: building blocks for nodetree structures
Georges Racinet <georges.racinet@octobus.net>
parents:
diff
changeset
|
178 } |
63db6657d280
rust-nodemap: building blocks for nodetree structures
Georges Racinet <georges.racinet@octobus.net>
parents:
diff
changeset
|
179 } |
63db6657d280
rust-nodemap: building blocks for nodetree structures
Georges Racinet <georges.racinet@octobus.net>
parents:
diff
changeset
|
180 |
63db6657d280
rust-nodemap: building blocks for nodetree structures
Georges Racinet <georges.racinet@octobus.net>
parents:
diff
changeset
|
181 impl From<Element> for RawElement { |
63db6657d280
rust-nodemap: building blocks for nodetree structures
Georges Racinet <georges.racinet@octobus.net>
parents:
diff
changeset
|
182 fn from(element: Element) -> RawElement { |
63db6657d280
rust-nodemap: building blocks for nodetree structures
Georges Racinet <georges.racinet@octobus.net>
parents:
diff
changeset
|
183 match element { |
63db6657d280
rust-nodemap: building blocks for nodetree structures
Georges Racinet <georges.racinet@octobus.net>
parents:
diff
changeset
|
184 Element::None => 0, |
63db6657d280
rust-nodemap: building blocks for nodetree structures
Georges Racinet <georges.racinet@octobus.net>
parents:
diff
changeset
|
185 Element::Block(i) => i as RawElement, |
63db6657d280
rust-nodemap: building blocks for nodetree structures
Georges Racinet <georges.racinet@octobus.net>
parents:
diff
changeset
|
186 Element::Rev(rev) => -rev - 2, |
63db6657d280
rust-nodemap: building blocks for nodetree structures
Georges Racinet <georges.racinet@octobus.net>
parents:
diff
changeset
|
187 } |
63db6657d280
rust-nodemap: building blocks for nodetree structures
Georges Racinet <georges.racinet@octobus.net>
parents:
diff
changeset
|
188 } |
63db6657d280
rust-nodemap: building blocks for nodetree structures
Georges Racinet <georges.racinet@octobus.net>
parents:
diff
changeset
|
189 } |
63db6657d280
rust-nodemap: building blocks for nodetree structures
Georges Racinet <georges.racinet@octobus.net>
parents:
diff
changeset
|
190 |
63db6657d280
rust-nodemap: building blocks for nodetree structures
Georges Racinet <georges.racinet@octobus.net>
parents:
diff
changeset
|
191 /// A logical block of the `NodeTree`, packed with a fixed size. |
63db6657d280
rust-nodemap: building blocks for nodetree structures
Georges Racinet <georges.racinet@octobus.net>
parents:
diff
changeset
|
192 /// |
63db6657d280
rust-nodemap: building blocks for nodetree structures
Georges Racinet <georges.racinet@octobus.net>
parents:
diff
changeset
|
193 /// These are always used in container types implementing `Index<Block>`, |
63db6657d280
rust-nodemap: building blocks for nodetree structures
Georges Racinet <georges.racinet@octobus.net>
parents:
diff
changeset
|
194 /// such as `&Block` |
63db6657d280
rust-nodemap: building blocks for nodetree structures
Georges Racinet <georges.racinet@octobus.net>
parents:
diff
changeset
|
195 /// |
63db6657d280
rust-nodemap: building blocks for nodetree structures
Georges Racinet <georges.racinet@octobus.net>
parents:
diff
changeset
|
196 /// As an array of integers, its ith element encodes that the |
63db6657d280
rust-nodemap: building blocks for nodetree structures
Georges Racinet <georges.racinet@octobus.net>
parents:
diff
changeset
|
197 /// ith potential edge from the block, representing the ith hexadecimal digit |
63db6657d280
rust-nodemap: building blocks for nodetree structures
Georges Racinet <georges.racinet@octobus.net>
parents:
diff
changeset
|
198 /// (nybble) `i` is either: |
63db6657d280
rust-nodemap: building blocks for nodetree structures
Georges Racinet <georges.racinet@octobus.net>
parents:
diff
changeset
|
199 /// |
63db6657d280
rust-nodemap: building blocks for nodetree structures
Georges Racinet <georges.racinet@octobus.net>
parents:
diff
changeset
|
200 /// - absent (value -1) |
63db6657d280
rust-nodemap: building blocks for nodetree structures
Georges Racinet <georges.racinet@octobus.net>
parents:
diff
changeset
|
201 /// - another `Block` in the same indexable container (value ≥ 0) |
63db6657d280
rust-nodemap: building blocks for nodetree structures
Georges Racinet <georges.racinet@octobus.net>
parents:
diff
changeset
|
202 /// - a `Revision` leaf (value ≤ -2) |
63db6657d280
rust-nodemap: building blocks for nodetree structures
Georges Racinet <georges.racinet@octobus.net>
parents:
diff
changeset
|
203 /// |
63db6657d280
rust-nodemap: building blocks for nodetree structures
Georges Racinet <georges.racinet@octobus.net>
parents:
diff
changeset
|
204 /// Endianness has to be fixed for consistency on shared storage across |
63db6657d280
rust-nodemap: building blocks for nodetree structures
Georges Racinet <georges.racinet@octobus.net>
parents:
diff
changeset
|
205 /// different architectures. |
63db6657d280
rust-nodemap: building blocks for nodetree structures
Georges Racinet <georges.racinet@octobus.net>
parents:
diff
changeset
|
206 /// |
63db6657d280
rust-nodemap: building blocks for nodetree structures
Georges Racinet <georges.racinet@octobus.net>
parents:
diff
changeset
|
207 /// A key difference with the C `nodetree` is that we need to be |
63db6657d280
rust-nodemap: building blocks for nodetree structures
Georges Racinet <georges.racinet@octobus.net>
parents:
diff
changeset
|
208 /// able to represent the [`Block`] at index 0, hence -1 is the empty marker |
63db6657d280
rust-nodemap: building blocks for nodetree structures
Georges Racinet <georges.racinet@octobus.net>
parents:
diff
changeset
|
209 /// rather than 0 and the `Revision` range upper limit of -2 instead of -1. |
63db6657d280
rust-nodemap: building blocks for nodetree structures
Georges Racinet <georges.racinet@octobus.net>
parents:
diff
changeset
|
210 /// |
63db6657d280
rust-nodemap: building blocks for nodetree structures
Georges Racinet <georges.racinet@octobus.net>
parents:
diff
changeset
|
211 /// Another related difference is that `NULL_REVISION` (-1) is not |
63db6657d280
rust-nodemap: building blocks for nodetree structures
Georges Racinet <georges.racinet@octobus.net>
parents:
diff
changeset
|
212 /// represented at all, because we want an immutable empty nodetree |
63db6657d280
rust-nodemap: building blocks for nodetree structures
Georges Racinet <georges.racinet@octobus.net>
parents:
diff
changeset
|
213 /// to be valid. |
63db6657d280
rust-nodemap: building blocks for nodetree structures
Georges Racinet <georges.racinet@octobus.net>
parents:
diff
changeset
|
214 |
44416
a98ba6983a63
rust-nodemap: input/output primitives
Georges Racinet <georges.racinet@octobus.net>
parents:
44390
diff
changeset
|
215 #[derive(Copy, Clone)] |
a98ba6983a63
rust-nodemap: input/output primitives
Georges Racinet <georges.racinet@octobus.net>
parents:
44390
diff
changeset
|
216 pub struct Block([u8; BLOCK_SIZE]); |
a98ba6983a63
rust-nodemap: input/output primitives
Georges Racinet <georges.racinet@octobus.net>
parents:
44390
diff
changeset
|
217 |
a98ba6983a63
rust-nodemap: input/output primitives
Georges Racinet <georges.racinet@octobus.net>
parents:
44390
diff
changeset
|
218 /// Not derivable for arrays of length >32 until const generics are stable |
a98ba6983a63
rust-nodemap: input/output primitives
Georges Racinet <georges.racinet@octobus.net>
parents:
44390
diff
changeset
|
219 impl PartialEq for Block { |
a98ba6983a63
rust-nodemap: input/output primitives
Georges Racinet <georges.racinet@octobus.net>
parents:
44390
diff
changeset
|
220 fn eq(&self, other: &Self) -> bool { |
44998
26114bd6ec60
rust: do a clippy pass
Rapha?l Gom?s <rgomes@octobus.net>
parents:
44421
diff
changeset
|
221 self.0[..] == other.0[..] |
44416
a98ba6983a63
rust-nodemap: input/output primitives
Georges Racinet <georges.racinet@octobus.net>
parents:
44390
diff
changeset
|
222 } |
a98ba6983a63
rust-nodemap: input/output primitives
Georges Racinet <georges.racinet@octobus.net>
parents:
44390
diff
changeset
|
223 } |
a98ba6983a63
rust-nodemap: input/output primitives
Georges Racinet <georges.racinet@octobus.net>
parents:
44390
diff
changeset
|
224 |
a98ba6983a63
rust-nodemap: input/output primitives
Georges Racinet <georges.racinet@octobus.net>
parents:
44390
diff
changeset
|
225 pub const BLOCK_SIZE: usize = 64; |
44227
63db6657d280
rust-nodemap: building blocks for nodetree structures
Georges Racinet <georges.racinet@octobus.net>
parents:
diff
changeset
|
226 |
63db6657d280
rust-nodemap: building blocks for nodetree structures
Georges Racinet <georges.racinet@octobus.net>
parents:
diff
changeset
|
227 impl Block { |
63db6657d280
rust-nodemap: building blocks for nodetree structures
Georges Racinet <georges.racinet@octobus.net>
parents:
diff
changeset
|
228 fn new() -> Self { |
44416
a98ba6983a63
rust-nodemap: input/output primitives
Georges Racinet <georges.racinet@octobus.net>
parents:
44390
diff
changeset
|
229 // -1 in 2's complement to create an absent node |
a98ba6983a63
rust-nodemap: input/output primitives
Georges Racinet <georges.racinet@octobus.net>
parents:
44390
diff
changeset
|
230 let byte: u8 = 255; |
a98ba6983a63
rust-nodemap: input/output primitives
Georges Racinet <georges.racinet@octobus.net>
parents:
44390
diff
changeset
|
231 Block([byte; BLOCK_SIZE]) |
44227
63db6657d280
rust-nodemap: building blocks for nodetree structures
Georges Racinet <georges.racinet@octobus.net>
parents:
diff
changeset
|
232 } |
63db6657d280
rust-nodemap: building blocks for nodetree structures
Georges Racinet <georges.racinet@octobus.net>
parents:
diff
changeset
|
233 |
63db6657d280
rust-nodemap: building blocks for nodetree structures
Georges Racinet <georges.racinet@octobus.net>
parents:
diff
changeset
|
234 fn get(&self, nybble: u8) -> Element { |
44416
a98ba6983a63
rust-nodemap: input/output primitives
Georges Racinet <georges.racinet@octobus.net>
parents:
44390
diff
changeset
|
235 let index = nybble as usize * mem::size_of::<RawElement>(); |
a98ba6983a63
rust-nodemap: input/output primitives
Georges Racinet <georges.racinet@octobus.net>
parents:
44390
diff
changeset
|
236 Element::from(RawElement::from_be_bytes([ |
a98ba6983a63
rust-nodemap: input/output primitives
Georges Racinet <georges.racinet@octobus.net>
parents:
44390
diff
changeset
|
237 self.0[index], |
a98ba6983a63
rust-nodemap: input/output primitives
Georges Racinet <georges.racinet@octobus.net>
parents:
44390
diff
changeset
|
238 self.0[index + 1], |
a98ba6983a63
rust-nodemap: input/output primitives
Georges Racinet <georges.racinet@octobus.net>
parents:
44390
diff
changeset
|
239 self.0[index + 2], |
a98ba6983a63
rust-nodemap: input/output primitives
Georges Racinet <georges.racinet@octobus.net>
parents:
44390
diff
changeset
|
240 self.0[index + 3], |
a98ba6983a63
rust-nodemap: input/output primitives
Georges Racinet <georges.racinet@octobus.net>
parents:
44390
diff
changeset
|
241 ])) |
44227
63db6657d280
rust-nodemap: building blocks for nodetree structures
Georges Racinet <georges.racinet@octobus.net>
parents:
diff
changeset
|
242 } |
63db6657d280
rust-nodemap: building blocks for nodetree structures
Georges Racinet <georges.racinet@octobus.net>
parents:
diff
changeset
|
243 |
63db6657d280
rust-nodemap: building blocks for nodetree structures
Georges Racinet <georges.racinet@octobus.net>
parents:
diff
changeset
|
244 fn set(&mut self, nybble: u8, element: Element) { |
44416
a98ba6983a63
rust-nodemap: input/output primitives
Georges Racinet <georges.racinet@octobus.net>
parents:
44390
diff
changeset
|
245 let values = RawElement::to_be_bytes(element.into()); |
a98ba6983a63
rust-nodemap: input/output primitives
Georges Racinet <georges.racinet@octobus.net>
parents:
44390
diff
changeset
|
246 let index = nybble as usize * mem::size_of::<RawElement>(); |
a98ba6983a63
rust-nodemap: input/output primitives
Georges Racinet <georges.racinet@octobus.net>
parents:
44390
diff
changeset
|
247 self.0[index] = values[0]; |
a98ba6983a63
rust-nodemap: input/output primitives
Georges Racinet <georges.racinet@octobus.net>
parents:
44390
diff
changeset
|
248 self.0[index + 1] = values[1]; |
a98ba6983a63
rust-nodemap: input/output primitives
Georges Racinet <georges.racinet@octobus.net>
parents:
44390
diff
changeset
|
249 self.0[index + 2] = values[2]; |
a98ba6983a63
rust-nodemap: input/output primitives
Georges Racinet <georges.racinet@octobus.net>
parents:
44390
diff
changeset
|
250 self.0[index + 3] = values[3]; |
44227
63db6657d280
rust-nodemap: building blocks for nodetree structures
Georges Racinet <georges.racinet@octobus.net>
parents:
diff
changeset
|
251 } |
63db6657d280
rust-nodemap: building blocks for nodetree structures
Georges Racinet <georges.racinet@octobus.net>
parents:
diff
changeset
|
252 } |
63db6657d280
rust-nodemap: building blocks for nodetree structures
Georges Racinet <georges.racinet@octobus.net>
parents:
diff
changeset
|
253 |
63db6657d280
rust-nodemap: building blocks for nodetree structures
Georges Racinet <georges.racinet@octobus.net>
parents:
diff
changeset
|
254 impl fmt::Debug for Block { |
63db6657d280
rust-nodemap: building blocks for nodetree structures
Georges Racinet <georges.racinet@octobus.net>
parents:
diff
changeset
|
255 /// sparse representation for testing and debugging purposes |
63db6657d280
rust-nodemap: building blocks for nodetree structures
Georges Racinet <georges.racinet@octobus.net>
parents:
diff
changeset
|
256 fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { |
63db6657d280
rust-nodemap: building blocks for nodetree structures
Georges Racinet <georges.racinet@octobus.net>
parents:
diff
changeset
|
257 f.debug_map() |
63db6657d280
rust-nodemap: building blocks for nodetree structures
Georges Racinet <georges.racinet@octobus.net>
parents:
diff
changeset
|
258 .entries((0..16).filter_map(|i| match self.get(i) { |
63db6657d280
rust-nodemap: building blocks for nodetree structures
Georges Racinet <georges.racinet@octobus.net>
parents:
diff
changeset
|
259 Element::None => None, |
63db6657d280
rust-nodemap: building blocks for nodetree structures
Georges Racinet <georges.racinet@octobus.net>
parents:
diff
changeset
|
260 element => Some((i, element)), |
63db6657d280
rust-nodemap: building blocks for nodetree structures
Georges Racinet <georges.racinet@octobus.net>
parents:
diff
changeset
|
261 })) |
63db6657d280
rust-nodemap: building blocks for nodetree structures
Georges Racinet <georges.racinet@octobus.net>
parents:
diff
changeset
|
262 .finish() |
63db6657d280
rust-nodemap: building blocks for nodetree structures
Georges Racinet <georges.racinet@octobus.net>
parents:
diff
changeset
|
263 } |
63db6657d280
rust-nodemap: building blocks for nodetree structures
Georges Racinet <georges.racinet@octobus.net>
parents:
diff
changeset
|
264 } |
63db6657d280
rust-nodemap: building blocks for nodetree structures
Georges Racinet <georges.racinet@octobus.net>
parents:
diff
changeset
|
265 |
44260
a19331456d48
rust-nodemap: mutable NodeTree data structure
Georges Racinet <georges.racinet@octobus.net>
parents:
44259
diff
changeset
|
266 /// A mutable 16-radix tree with the root block logically at the end |
a19331456d48
rust-nodemap: mutable NodeTree data structure
Georges Racinet <georges.racinet@octobus.net>
parents:
44259
diff
changeset
|
267 /// |
a19331456d48
rust-nodemap: mutable NodeTree data structure
Georges Racinet <georges.racinet@octobus.net>
parents:
44259
diff
changeset
|
268 /// Because of the append only nature of our node trees, we need to |
a19331456d48
rust-nodemap: mutable NodeTree data structure
Georges Racinet <georges.racinet@octobus.net>
parents:
44259
diff
changeset
|
269 /// keep the original untouched and store new blocks separately. |
a19331456d48
rust-nodemap: mutable NodeTree data structure
Georges Racinet <georges.racinet@octobus.net>
parents:
44259
diff
changeset
|
270 /// |
a19331456d48
rust-nodemap: mutable NodeTree data structure
Georges Racinet <georges.racinet@octobus.net>
parents:
44259
diff
changeset
|
271 /// The mutable root `Block` is kept apart so that we don't have to rebump |
a19331456d48
rust-nodemap: mutable NodeTree data structure
Georges Racinet <georges.racinet@octobus.net>
parents:
44259
diff
changeset
|
272 /// it on each insertion. |
44258
e52401a95b94
rust-nodemap: NodeMap trait with simplest implementation
Georges Racinet <georges.racinet@octobus.net>
parents:
44227
diff
changeset
|
273 pub struct NodeTree { |
e52401a95b94
rust-nodemap: NodeMap trait with simplest implementation
Georges Racinet <georges.racinet@octobus.net>
parents:
44227
diff
changeset
|
274 readonly: Box<dyn Deref<Target = [Block]> + Send>, |
44260
a19331456d48
rust-nodemap: mutable NodeTree data structure
Georges Racinet <georges.racinet@octobus.net>
parents:
44259
diff
changeset
|
275 growable: Vec<Block>, |
a19331456d48
rust-nodemap: mutable NodeTree data structure
Georges Racinet <georges.racinet@octobus.net>
parents:
44259
diff
changeset
|
276 root: Block, |
44420
6329ce04c69f
rust-nodemap: accounting for dead blocks
Georges Racinet <georges.racinet@octobus.net>
parents:
44419
diff
changeset
|
277 masked_inner_blocks: usize, |
44258
e52401a95b94
rust-nodemap: NodeMap trait with simplest implementation
Georges Racinet <georges.racinet@octobus.net>
parents:
44227
diff
changeset
|
278 } |
e52401a95b94
rust-nodemap: NodeMap trait with simplest implementation
Georges Racinet <georges.racinet@octobus.net>
parents:
44227
diff
changeset
|
279 |
44259
220d4d2e3185
rust-nodemap: abstracting the indexing
Georges Racinet <georges.racinet@octobus.net>
parents:
44258
diff
changeset
|
280 impl Index<usize> for NodeTree { |
220d4d2e3185
rust-nodemap: abstracting the indexing
Georges Racinet <georges.racinet@octobus.net>
parents:
44258
diff
changeset
|
281 type Output = Block; |
220d4d2e3185
rust-nodemap: abstracting the indexing
Georges Racinet <georges.racinet@octobus.net>
parents:
44258
diff
changeset
|
282 |
220d4d2e3185
rust-nodemap: abstracting the indexing
Georges Racinet <georges.racinet@octobus.net>
parents:
44258
diff
changeset
|
283 fn index(&self, i: usize) -> &Block { |
44260
a19331456d48
rust-nodemap: mutable NodeTree data structure
Georges Racinet <georges.racinet@octobus.net>
parents:
44259
diff
changeset
|
284 let ro_len = self.readonly.len(); |
a19331456d48
rust-nodemap: mutable NodeTree data structure
Georges Racinet <georges.racinet@octobus.net>
parents:
44259
diff
changeset
|
285 if i < ro_len { |
a19331456d48
rust-nodemap: mutable NodeTree data structure
Georges Racinet <georges.racinet@octobus.net>
parents:
44259
diff
changeset
|
286 &self.readonly[i] |
a19331456d48
rust-nodemap: mutable NodeTree data structure
Georges Racinet <georges.racinet@octobus.net>
parents:
44259
diff
changeset
|
287 } else if i == ro_len + self.growable.len() { |
a19331456d48
rust-nodemap: mutable NodeTree data structure
Georges Racinet <georges.racinet@octobus.net>
parents:
44259
diff
changeset
|
288 &self.root |
a19331456d48
rust-nodemap: mutable NodeTree data structure
Georges Racinet <georges.racinet@octobus.net>
parents:
44259
diff
changeset
|
289 } else { |
a19331456d48
rust-nodemap: mutable NodeTree data structure
Georges Racinet <georges.racinet@octobus.net>
parents:
44259
diff
changeset
|
290 &self.growable[i - ro_len] |
a19331456d48
rust-nodemap: mutable NodeTree data structure
Georges Racinet <georges.racinet@octobus.net>
parents:
44259
diff
changeset
|
291 } |
44259
220d4d2e3185
rust-nodemap: abstracting the indexing
Georges Racinet <georges.racinet@octobus.net>
parents:
44258
diff
changeset
|
292 } |
220d4d2e3185
rust-nodemap: abstracting the indexing
Georges Racinet <georges.racinet@octobus.net>
parents:
44258
diff
changeset
|
293 } |
220d4d2e3185
rust-nodemap: abstracting the indexing
Georges Racinet <georges.racinet@octobus.net>
parents:
44258
diff
changeset
|
294 |
44258
e52401a95b94
rust-nodemap: NodeMap trait with simplest implementation
Georges Racinet <georges.racinet@octobus.net>
parents:
44227
diff
changeset
|
295 /// Return `None` unless the `Node` for `rev` has given prefix in `index`. |
44416
a98ba6983a63
rust-nodemap: input/output primitives
Georges Racinet <georges.racinet@octobus.net>
parents:
44390
diff
changeset
|
296 fn has_prefix_or_none( |
44258
e52401a95b94
rust-nodemap: NodeMap trait with simplest implementation
Georges Racinet <georges.racinet@octobus.net>
parents:
44227
diff
changeset
|
297 idx: &impl RevlogIndex, |
44416
a98ba6983a63
rust-nodemap: input/output primitives
Georges Racinet <georges.racinet@octobus.net>
parents:
44390
diff
changeset
|
298 prefix: NodePrefixRef, |
44258
e52401a95b94
rust-nodemap: NodeMap trait with simplest implementation
Georges Racinet <georges.racinet@octobus.net>
parents:
44227
diff
changeset
|
299 rev: Revision, |
e52401a95b94
rust-nodemap: NodeMap trait with simplest implementation
Georges Racinet <georges.racinet@octobus.net>
parents:
44227
diff
changeset
|
300 ) -> Result<Option<Revision>, NodeMapError> { |
e52401a95b94
rust-nodemap: NodeMap trait with simplest implementation
Georges Racinet <georges.racinet@octobus.net>
parents:
44227
diff
changeset
|
301 idx.node(rev) |
e52401a95b94
rust-nodemap: NodeMap trait with simplest implementation
Georges Racinet <georges.racinet@octobus.net>
parents:
44227
diff
changeset
|
302 .ok_or_else(|| NodeMapError::RevisionNotInIndex(rev)) |
e52401a95b94
rust-nodemap: NodeMap trait with simplest implementation
Georges Racinet <georges.racinet@octobus.net>
parents:
44227
diff
changeset
|
303 .map(|node| { |
e52401a95b94
rust-nodemap: NodeMap trait with simplest implementation
Georges Racinet <georges.racinet@octobus.net>
parents:
44227
diff
changeset
|
304 if prefix.is_prefix_of(node) { |
e52401a95b94
rust-nodemap: NodeMap trait with simplest implementation
Georges Racinet <georges.racinet@octobus.net>
parents:
44227
diff
changeset
|
305 Some(rev) |
e52401a95b94
rust-nodemap: NodeMap trait with simplest implementation
Georges Racinet <georges.racinet@octobus.net>
parents:
44227
diff
changeset
|
306 } else { |
e52401a95b94
rust-nodemap: NodeMap trait with simplest implementation
Georges Racinet <georges.racinet@octobus.net>
parents:
44227
diff
changeset
|
307 None |
e52401a95b94
rust-nodemap: NodeMap trait with simplest implementation
Georges Racinet <georges.racinet@octobus.net>
parents:
44227
diff
changeset
|
308 } |
e52401a95b94
rust-nodemap: NodeMap trait with simplest implementation
Georges Racinet <georges.racinet@octobus.net>
parents:
44227
diff
changeset
|
309 }) |
e52401a95b94
rust-nodemap: NodeMap trait with simplest implementation
Georges Racinet <georges.racinet@octobus.net>
parents:
44227
diff
changeset
|
310 } |
e52401a95b94
rust-nodemap: NodeMap trait with simplest implementation
Georges Racinet <georges.racinet@octobus.net>
parents:
44227
diff
changeset
|
311 |
44418
00d251d32007
rust-nodemap: special case for prefixes of NULL_NODE
Georges Racinet <georges.racinet@octobus.net>
parents:
44416
diff
changeset
|
312 /// validate that the candidate's node starts indeed with given prefix, |
00d251d32007
rust-nodemap: special case for prefixes of NULL_NODE
Georges Racinet <georges.racinet@octobus.net>
parents:
44416
diff
changeset
|
313 /// and treat ambiguities related to `NULL_REVISION`. |
00d251d32007
rust-nodemap: special case for prefixes of NULL_NODE
Georges Racinet <georges.racinet@octobus.net>
parents:
44416
diff
changeset
|
314 /// |
00d251d32007
rust-nodemap: special case for prefixes of NULL_NODE
Georges Racinet <georges.racinet@octobus.net>
parents:
44416
diff
changeset
|
315 /// From the data in the NodeTree, one can only conclude that some |
00d251d32007
rust-nodemap: special case for prefixes of NULL_NODE
Georges Racinet <georges.racinet@octobus.net>
parents:
44416
diff
changeset
|
316 /// revision is the only one for a *subprefix* of the one being looked up. |
00d251d32007
rust-nodemap: special case for prefixes of NULL_NODE
Georges Racinet <georges.racinet@octobus.net>
parents:
44416
diff
changeset
|
317 fn validate_candidate( |
00d251d32007
rust-nodemap: special case for prefixes of NULL_NODE
Georges Racinet <georges.racinet@octobus.net>
parents:
44416
diff
changeset
|
318 idx: &impl RevlogIndex, |
00d251d32007
rust-nodemap: special case for prefixes of NULL_NODE
Georges Racinet <georges.racinet@octobus.net>
parents:
44416
diff
changeset
|
319 prefix: NodePrefixRef, |
44419
5ac1eecc9c64
rust-nodemap: core implementation for shortest
Georges Racinet <georges.racinet@octobus.net>
parents:
44418
diff
changeset
|
320 candidate: (Option<Revision>, usize), |
5ac1eecc9c64
rust-nodemap: core implementation for shortest
Georges Racinet <georges.racinet@octobus.net>
parents:
44418
diff
changeset
|
321 ) -> Result<(Option<Revision>, usize), NodeMapError> { |
5ac1eecc9c64
rust-nodemap: core implementation for shortest
Georges Racinet <georges.racinet@octobus.net>
parents:
44418
diff
changeset
|
322 let (rev, steps) = candidate; |
5ac1eecc9c64
rust-nodemap: core implementation for shortest
Georges Racinet <georges.racinet@octobus.net>
parents:
44418
diff
changeset
|
323 if let Some(nz_nybble) = prefix.first_different_nybble(&NULL_NODE) { |
5ac1eecc9c64
rust-nodemap: core implementation for shortest
Georges Racinet <georges.racinet@octobus.net>
parents:
44418
diff
changeset
|
324 rev.map_or(Ok((None, steps)), |r| { |
5ac1eecc9c64
rust-nodemap: core implementation for shortest
Georges Racinet <georges.racinet@octobus.net>
parents:
44418
diff
changeset
|
325 has_prefix_or_none(idx, prefix, r) |
5ac1eecc9c64
rust-nodemap: core implementation for shortest
Georges Racinet <georges.racinet@octobus.net>
parents:
44418
diff
changeset
|
326 .map(|opt| (opt, max(steps, nz_nybble + 1))) |
5ac1eecc9c64
rust-nodemap: core implementation for shortest
Georges Racinet <georges.racinet@octobus.net>
parents:
44418
diff
changeset
|
327 }) |
5ac1eecc9c64
rust-nodemap: core implementation for shortest
Georges Racinet <georges.racinet@octobus.net>
parents:
44418
diff
changeset
|
328 } else { |
5ac1eecc9c64
rust-nodemap: core implementation for shortest
Georges Racinet <georges.racinet@octobus.net>
parents:
44418
diff
changeset
|
329 // the prefix is only made of zeros; NULL_REVISION always matches it |
44418
00d251d32007
rust-nodemap: special case for prefixes of NULL_NODE
Georges Racinet <georges.racinet@octobus.net>
parents:
44416
diff
changeset
|
330 // and any other *valid* result is an ambiguity |
00d251d32007
rust-nodemap: special case for prefixes of NULL_NODE
Georges Racinet <georges.racinet@octobus.net>
parents:
44416
diff
changeset
|
331 match rev { |
44419
5ac1eecc9c64
rust-nodemap: core implementation for shortest
Georges Racinet <georges.racinet@octobus.net>
parents:
44418
diff
changeset
|
332 None => Ok((Some(NULL_REVISION), steps + 1)), |
44418
00d251d32007
rust-nodemap: special case for prefixes of NULL_NODE
Georges Racinet <georges.racinet@octobus.net>
parents:
44416
diff
changeset
|
333 Some(r) => match has_prefix_or_none(idx, prefix, r)? { |
44419
5ac1eecc9c64
rust-nodemap: core implementation for shortest
Georges Racinet <georges.racinet@octobus.net>
parents:
44418
diff
changeset
|
334 None => Ok((Some(NULL_REVISION), steps + 1)), |
44418
00d251d32007
rust-nodemap: special case for prefixes of NULL_NODE
Georges Racinet <georges.racinet@octobus.net>
parents:
44416
diff
changeset
|
335 _ => Err(NodeMapError::MultipleResults), |
00d251d32007
rust-nodemap: special case for prefixes of NULL_NODE
Georges Racinet <georges.racinet@octobus.net>
parents:
44416
diff
changeset
|
336 }, |
00d251d32007
rust-nodemap: special case for prefixes of NULL_NODE
Georges Racinet <georges.racinet@octobus.net>
parents:
44416
diff
changeset
|
337 } |
00d251d32007
rust-nodemap: special case for prefixes of NULL_NODE
Georges Racinet <georges.racinet@octobus.net>
parents:
44416
diff
changeset
|
338 } |
00d251d32007
rust-nodemap: special case for prefixes of NULL_NODE
Georges Racinet <georges.racinet@octobus.net>
parents:
44416
diff
changeset
|
339 } |
00d251d32007
rust-nodemap: special case for prefixes of NULL_NODE
Georges Racinet <georges.racinet@octobus.net>
parents:
44416
diff
changeset
|
340 |
44258
e52401a95b94
rust-nodemap: NodeMap trait with simplest implementation
Georges Racinet <georges.racinet@octobus.net>
parents:
44227
diff
changeset
|
341 impl NodeTree { |
44260
a19331456d48
rust-nodemap: mutable NodeTree data structure
Georges Racinet <georges.racinet@octobus.net>
parents:
44259
diff
changeset
|
342 /// Initiate a NodeTree from an immutable slice-like of `Block` |
a19331456d48
rust-nodemap: mutable NodeTree data structure
Georges Racinet <georges.racinet@octobus.net>
parents:
44259
diff
changeset
|
343 /// |
a19331456d48
rust-nodemap: mutable NodeTree data structure
Georges Racinet <georges.racinet@octobus.net>
parents:
44259
diff
changeset
|
344 /// We keep `readonly` and clone its root block if it isn't empty. |
a19331456d48
rust-nodemap: mutable NodeTree data structure
Georges Racinet <georges.racinet@octobus.net>
parents:
44259
diff
changeset
|
345 fn new(readonly: Box<dyn Deref<Target = [Block]> + Send>) -> Self { |
44998
26114bd6ec60
rust: do a clippy pass
Rapha?l Gom?s <rgomes@octobus.net>
parents:
44421
diff
changeset
|
346 let root = readonly.last().cloned().unwrap_or_else(Block::new); |
44260
a19331456d48
rust-nodemap: mutable NodeTree data structure
Georges Racinet <georges.racinet@octobus.net>
parents:
44259
diff
changeset
|
347 NodeTree { |
44998
26114bd6ec60
rust: do a clippy pass
Rapha?l Gom?s <rgomes@octobus.net>
parents:
44421
diff
changeset
|
348 readonly, |
44260
a19331456d48
rust-nodemap: mutable NodeTree data structure
Georges Racinet <georges.racinet@octobus.net>
parents:
44259
diff
changeset
|
349 growable: Vec::new(), |
44998
26114bd6ec60
rust: do a clippy pass
Rapha?l Gom?s <rgomes@octobus.net>
parents:
44421
diff
changeset
|
350 root, |
44420
6329ce04c69f
rust-nodemap: accounting for dead blocks
Georges Racinet <georges.racinet@octobus.net>
parents:
44419
diff
changeset
|
351 masked_inner_blocks: 0, |
44260
a19331456d48
rust-nodemap: mutable NodeTree data structure
Georges Racinet <georges.racinet@octobus.net>
parents:
44259
diff
changeset
|
352 } |
44259
220d4d2e3185
rust-nodemap: abstracting the indexing
Georges Racinet <georges.racinet@octobus.net>
parents:
44258
diff
changeset
|
353 } |
220d4d2e3185
rust-nodemap: abstracting the indexing
Georges Racinet <georges.racinet@octobus.net>
parents:
44258
diff
changeset
|
354 |
44416
a98ba6983a63
rust-nodemap: input/output primitives
Georges Racinet <georges.racinet@octobus.net>
parents:
44390
diff
changeset
|
355 /// Create from an opaque bunch of bytes |
a98ba6983a63
rust-nodemap: input/output primitives
Georges Racinet <georges.racinet@octobus.net>
parents:
44390
diff
changeset
|
356 /// |
a98ba6983a63
rust-nodemap: input/output primitives
Georges Racinet <georges.racinet@octobus.net>
parents:
44390
diff
changeset
|
357 /// The created `NodeTreeBytes` from `buffer`, |
a98ba6983a63
rust-nodemap: input/output primitives
Georges Racinet <georges.racinet@octobus.net>
parents:
44390
diff
changeset
|
358 /// of which exactly `amount` bytes are used. |
a98ba6983a63
rust-nodemap: input/output primitives
Georges Racinet <georges.racinet@octobus.net>
parents:
44390
diff
changeset
|
359 /// |
a98ba6983a63
rust-nodemap: input/output primitives
Georges Racinet <georges.racinet@octobus.net>
parents:
44390
diff
changeset
|
360 /// - `buffer` could be derived from `PyBuffer` and `Mmap` objects. |
a98ba6983a63
rust-nodemap: input/output primitives
Georges Racinet <georges.racinet@octobus.net>
parents:
44390
diff
changeset
|
361 /// - `offset` allows for the final file format to include fixed data |
a98ba6983a63
rust-nodemap: input/output primitives
Georges Racinet <georges.racinet@octobus.net>
parents:
44390
diff
changeset
|
362 /// (generation number, behavioural flags) |
a98ba6983a63
rust-nodemap: input/output primitives
Georges Racinet <georges.racinet@octobus.net>
parents:
44390
diff
changeset
|
363 /// - `amount` is expressed in bytes, and is not automatically derived from |
a98ba6983a63
rust-nodemap: input/output primitives
Georges Racinet <georges.racinet@octobus.net>
parents:
44390
diff
changeset
|
364 /// `bytes`, so that a caller that manages them atomically can perform |
a98ba6983a63
rust-nodemap: input/output primitives
Georges Racinet <georges.racinet@octobus.net>
parents:
44390
diff
changeset
|
365 /// temporary disk serializations and still rollback easily if needed. |
a98ba6983a63
rust-nodemap: input/output primitives
Georges Racinet <georges.racinet@octobus.net>
parents:
44390
diff
changeset
|
366 /// First use-case for this would be to support Mercurial shell hooks. |
a98ba6983a63
rust-nodemap: input/output primitives
Georges Racinet <georges.racinet@octobus.net>
parents:
44390
diff
changeset
|
367 /// |
a98ba6983a63
rust-nodemap: input/output primitives
Georges Racinet <georges.racinet@octobus.net>
parents:
44390
diff
changeset
|
368 /// panics if `buffer` is smaller than `amount` |
a98ba6983a63
rust-nodemap: input/output primitives
Georges Racinet <georges.racinet@octobus.net>
parents:
44390
diff
changeset
|
369 pub fn load_bytes( |
a98ba6983a63
rust-nodemap: input/output primitives
Georges Racinet <georges.racinet@octobus.net>
parents:
44390
diff
changeset
|
370 bytes: Box<dyn Deref<Target = [u8]> + Send>, |
a98ba6983a63
rust-nodemap: input/output primitives
Georges Racinet <georges.racinet@octobus.net>
parents:
44390
diff
changeset
|
371 amount: usize, |
a98ba6983a63
rust-nodemap: input/output primitives
Georges Racinet <georges.racinet@octobus.net>
parents:
44390
diff
changeset
|
372 ) -> Self { |
a98ba6983a63
rust-nodemap: input/output primitives
Georges Racinet <georges.racinet@octobus.net>
parents:
44390
diff
changeset
|
373 NodeTree::new(Box::new(NodeTreeBytes::new(bytes, amount))) |
a98ba6983a63
rust-nodemap: input/output primitives
Georges Racinet <georges.racinet@octobus.net>
parents:
44390
diff
changeset
|
374 } |
a98ba6983a63
rust-nodemap: input/output primitives
Georges Racinet <georges.racinet@octobus.net>
parents:
44390
diff
changeset
|
375 |
a98ba6983a63
rust-nodemap: input/output primitives
Georges Racinet <georges.racinet@octobus.net>
parents:
44390
diff
changeset
|
376 /// Retrieve added `Block` and the original immutable data |
a98ba6983a63
rust-nodemap: input/output primitives
Georges Racinet <georges.racinet@octobus.net>
parents:
44390
diff
changeset
|
377 pub fn into_readonly_and_added( |
a98ba6983a63
rust-nodemap: input/output primitives
Georges Racinet <georges.racinet@octobus.net>
parents:
44390
diff
changeset
|
378 self, |
a98ba6983a63
rust-nodemap: input/output primitives
Georges Racinet <georges.racinet@octobus.net>
parents:
44390
diff
changeset
|
379 ) -> (Box<dyn Deref<Target = [Block]> + Send>, Vec<Block>) { |
a98ba6983a63
rust-nodemap: input/output primitives
Georges Racinet <georges.racinet@octobus.net>
parents:
44390
diff
changeset
|
380 let mut vec = self.growable; |
a98ba6983a63
rust-nodemap: input/output primitives
Georges Racinet <georges.racinet@octobus.net>
parents:
44390
diff
changeset
|
381 let readonly = self.readonly; |
a98ba6983a63
rust-nodemap: input/output primitives
Georges Racinet <georges.racinet@octobus.net>
parents:
44390
diff
changeset
|
382 if readonly.last() != Some(&self.root) { |
a98ba6983a63
rust-nodemap: input/output primitives
Georges Racinet <georges.racinet@octobus.net>
parents:
44390
diff
changeset
|
383 vec.push(self.root); |
a98ba6983a63
rust-nodemap: input/output primitives
Georges Racinet <georges.racinet@octobus.net>
parents:
44390
diff
changeset
|
384 } |
a98ba6983a63
rust-nodemap: input/output primitives
Georges Racinet <georges.racinet@octobus.net>
parents:
44390
diff
changeset
|
385 (readonly, vec) |
a98ba6983a63
rust-nodemap: input/output primitives
Georges Racinet <georges.racinet@octobus.net>
parents:
44390
diff
changeset
|
386 } |
a98ba6983a63
rust-nodemap: input/output primitives
Georges Racinet <georges.racinet@octobus.net>
parents:
44390
diff
changeset
|
387 |
a98ba6983a63
rust-nodemap: input/output primitives
Georges Racinet <georges.racinet@octobus.net>
parents:
44390
diff
changeset
|
388 /// Retrieve added `Blocks` as bytes, ready to be written to persistent |
a98ba6983a63
rust-nodemap: input/output primitives
Georges Racinet <georges.racinet@octobus.net>
parents:
44390
diff
changeset
|
389 /// storage |
a98ba6983a63
rust-nodemap: input/output primitives
Georges Racinet <georges.racinet@octobus.net>
parents:
44390
diff
changeset
|
390 pub fn into_readonly_and_added_bytes( |
a98ba6983a63
rust-nodemap: input/output primitives
Georges Racinet <georges.racinet@octobus.net>
parents:
44390
diff
changeset
|
391 self, |
a98ba6983a63
rust-nodemap: input/output primitives
Georges Racinet <georges.racinet@octobus.net>
parents:
44390
diff
changeset
|
392 ) -> (Box<dyn Deref<Target = [Block]> + Send>, Vec<u8>) { |
a98ba6983a63
rust-nodemap: input/output primitives
Georges Racinet <georges.racinet@octobus.net>
parents:
44390
diff
changeset
|
393 let (readonly, vec) = self.into_readonly_and_added(); |
a98ba6983a63
rust-nodemap: input/output primitives
Georges Racinet <georges.racinet@octobus.net>
parents:
44390
diff
changeset
|
394 // Prevent running `v`'s destructor so we are in complete control |
a98ba6983a63
rust-nodemap: input/output primitives
Georges Racinet <georges.racinet@octobus.net>
parents:
44390
diff
changeset
|
395 // of the allocation. |
a98ba6983a63
rust-nodemap: input/output primitives
Georges Racinet <georges.racinet@octobus.net>
parents:
44390
diff
changeset
|
396 let vec = mem::ManuallyDrop::new(vec); |
a98ba6983a63
rust-nodemap: input/output primitives
Georges Racinet <georges.racinet@octobus.net>
parents:
44390
diff
changeset
|
397 |
a98ba6983a63
rust-nodemap: input/output primitives
Georges Racinet <georges.racinet@octobus.net>
parents:
44390
diff
changeset
|
398 // Transmute the `Vec<Block>` to a `Vec<u8>`. Blocks are contiguous |
a98ba6983a63
rust-nodemap: input/output primitives
Georges Racinet <georges.racinet@octobus.net>
parents:
44390
diff
changeset
|
399 // bytes, so this is perfectly safe. |
a98ba6983a63
rust-nodemap: input/output primitives
Georges Racinet <georges.racinet@octobus.net>
parents:
44390
diff
changeset
|
400 let bytes = unsafe { |
a98ba6983a63
rust-nodemap: input/output primitives
Georges Racinet <georges.racinet@octobus.net>
parents:
44390
diff
changeset
|
401 // Assert that `Block` hasn't been changed and has no padding |
a98ba6983a63
rust-nodemap: input/output primitives
Georges Racinet <georges.racinet@octobus.net>
parents:
44390
diff
changeset
|
402 let _: [u8; 4 * BLOCK_SIZE] = |
a98ba6983a63
rust-nodemap: input/output primitives
Georges Racinet <georges.racinet@octobus.net>
parents:
44390
diff
changeset
|
403 std::mem::transmute([Block::new(); 4]); |
a98ba6983a63
rust-nodemap: input/output primitives
Georges Racinet <georges.racinet@octobus.net>
parents:
44390
diff
changeset
|
404 |
a98ba6983a63
rust-nodemap: input/output primitives
Georges Racinet <georges.racinet@octobus.net>
parents:
44390
diff
changeset
|
405 // /!\ Any use of `vec` after this is use-after-free. |
a98ba6983a63
rust-nodemap: input/output primitives
Georges Racinet <georges.racinet@octobus.net>
parents:
44390
diff
changeset
|
406 // TODO: use `into_raw_parts` once stabilized |
a98ba6983a63
rust-nodemap: input/output primitives
Georges Racinet <georges.racinet@octobus.net>
parents:
44390
diff
changeset
|
407 Vec::from_raw_parts( |
a98ba6983a63
rust-nodemap: input/output primitives
Georges Racinet <georges.racinet@octobus.net>
parents:
44390
diff
changeset
|
408 vec.as_ptr() as *mut u8, |
a98ba6983a63
rust-nodemap: input/output primitives
Georges Racinet <georges.racinet@octobus.net>
parents:
44390
diff
changeset
|
409 vec.len() * BLOCK_SIZE, |
a98ba6983a63
rust-nodemap: input/output primitives
Georges Racinet <georges.racinet@octobus.net>
parents:
44390
diff
changeset
|
410 vec.capacity() * BLOCK_SIZE, |
a98ba6983a63
rust-nodemap: input/output primitives
Georges Racinet <georges.racinet@octobus.net>
parents:
44390
diff
changeset
|
411 ) |
a98ba6983a63
rust-nodemap: input/output primitives
Georges Racinet <georges.racinet@octobus.net>
parents:
44390
diff
changeset
|
412 }; |
a98ba6983a63
rust-nodemap: input/output primitives
Georges Racinet <georges.racinet@octobus.net>
parents:
44390
diff
changeset
|
413 (readonly, bytes) |
a98ba6983a63
rust-nodemap: input/output primitives
Georges Racinet <georges.racinet@octobus.net>
parents:
44390
diff
changeset
|
414 } |
a98ba6983a63
rust-nodemap: input/output primitives
Georges Racinet <georges.racinet@octobus.net>
parents:
44390
diff
changeset
|
415 |
44260
a19331456d48
rust-nodemap: mutable NodeTree data structure
Georges Racinet <georges.racinet@octobus.net>
parents:
44259
diff
changeset
|
416 /// Total number of blocks |
a19331456d48
rust-nodemap: mutable NodeTree data structure
Georges Racinet <georges.racinet@octobus.net>
parents:
44259
diff
changeset
|
417 fn len(&self) -> usize { |
a19331456d48
rust-nodemap: mutable NodeTree data structure
Georges Racinet <georges.racinet@octobus.net>
parents:
44259
diff
changeset
|
418 self.readonly.len() + self.growable.len() + 1 |
a19331456d48
rust-nodemap: mutable NodeTree data structure
Georges Racinet <georges.racinet@octobus.net>
parents:
44259
diff
changeset
|
419 } |
a19331456d48
rust-nodemap: mutable NodeTree data structure
Georges Racinet <georges.racinet@octobus.net>
parents:
44259
diff
changeset
|
420 |
a19331456d48
rust-nodemap: mutable NodeTree data structure
Georges Racinet <georges.racinet@octobus.net>
parents:
44259
diff
changeset
|
421 /// Implemented for completeness |
a19331456d48
rust-nodemap: mutable NodeTree data structure
Georges Racinet <georges.racinet@octobus.net>
parents:
44259
diff
changeset
|
422 /// |
a19331456d48
rust-nodemap: mutable NodeTree data structure
Georges Racinet <georges.racinet@octobus.net>
parents:
44259
diff
changeset
|
423 /// A `NodeTree` always has at least the mutable root block. |
a19331456d48
rust-nodemap: mutable NodeTree data structure
Georges Racinet <georges.racinet@octobus.net>
parents:
44259
diff
changeset
|
424 #[allow(dead_code)] |
44259
220d4d2e3185
rust-nodemap: abstracting the indexing
Georges Racinet <georges.racinet@octobus.net>
parents:
44258
diff
changeset
|
425 fn is_empty(&self) -> bool { |
44260
a19331456d48
rust-nodemap: mutable NodeTree data structure
Georges Racinet <georges.racinet@octobus.net>
parents:
44259
diff
changeset
|
426 false |
44259
220d4d2e3185
rust-nodemap: abstracting the indexing
Georges Racinet <georges.racinet@octobus.net>
parents:
44258
diff
changeset
|
427 } |
220d4d2e3185
rust-nodemap: abstracting the indexing
Georges Racinet <georges.racinet@octobus.net>
parents:
44258
diff
changeset
|
428 |
44258
e52401a95b94
rust-nodemap: NodeMap trait with simplest implementation
Georges Racinet <georges.racinet@octobus.net>
parents:
44227
diff
changeset
|
429 /// Main working method for `NodeTree` searches |
44419
5ac1eecc9c64
rust-nodemap: core implementation for shortest
Georges Racinet <georges.racinet@octobus.net>
parents:
44418
diff
changeset
|
430 /// |
5ac1eecc9c64
rust-nodemap: core implementation for shortest
Georges Racinet <georges.racinet@octobus.net>
parents:
44418
diff
changeset
|
431 /// The first returned value is the result of analysing `NodeTree` data |
5ac1eecc9c64
rust-nodemap: core implementation for shortest
Georges Racinet <georges.racinet@octobus.net>
parents:
44418
diff
changeset
|
432 /// *alone*: whereas `None` guarantees that the given prefix is absent |
5ac1eecc9c64
rust-nodemap: core implementation for shortest
Georges Racinet <georges.racinet@octobus.net>
parents:
44418
diff
changeset
|
433 /// from the `NodeTree` data (but still could match `NULL_NODE`), with |
5ac1eecc9c64
rust-nodemap: core implementation for shortest
Georges Racinet <georges.racinet@octobus.net>
parents:
44418
diff
changeset
|
434 /// `Some(rev)`, it is to be understood that `rev` is the unique `Revision` |
5ac1eecc9c64
rust-nodemap: core implementation for shortest
Georges Racinet <georges.racinet@octobus.net>
parents:
44418
diff
changeset
|
435 /// that could match the prefix. Actually, all that can be inferred from |
5ac1eecc9c64
rust-nodemap: core implementation for shortest
Georges Racinet <georges.racinet@octobus.net>
parents:
44418
diff
changeset
|
436 /// the `NodeTree` data is that `rev` is the revision with the longest |
5ac1eecc9c64
rust-nodemap: core implementation for shortest
Georges Racinet <georges.racinet@octobus.net>
parents:
44418
diff
changeset
|
437 /// common node prefix with the given prefix. |
5ac1eecc9c64
rust-nodemap: core implementation for shortest
Georges Racinet <georges.racinet@octobus.net>
parents:
44418
diff
changeset
|
438 /// |
5ac1eecc9c64
rust-nodemap: core implementation for shortest
Georges Racinet <georges.racinet@octobus.net>
parents:
44418
diff
changeset
|
439 /// The second returned value is the size of the smallest subprefix |
5ac1eecc9c64
rust-nodemap: core implementation for shortest
Georges Racinet <georges.racinet@octobus.net>
parents:
44418
diff
changeset
|
440 /// of `prefix` that would give the same result, i.e. not the |
5ac1eecc9c64
rust-nodemap: core implementation for shortest
Georges Racinet <georges.racinet@octobus.net>
parents:
44418
diff
changeset
|
441 /// `MultipleResults` error variant (again, using only the data of the |
5ac1eecc9c64
rust-nodemap: core implementation for shortest
Georges Racinet <georges.racinet@octobus.net>
parents:
44418
diff
changeset
|
442 /// `NodeTree`). |
5ac1eecc9c64
rust-nodemap: core implementation for shortest
Georges Racinet <georges.racinet@octobus.net>
parents:
44418
diff
changeset
|
443 fn lookup( |
44258
e52401a95b94
rust-nodemap: NodeMap trait with simplest implementation
Georges Racinet <georges.racinet@octobus.net>
parents:
44227
diff
changeset
|
444 &self, |
44419
5ac1eecc9c64
rust-nodemap: core implementation for shortest
Georges Racinet <georges.racinet@octobus.net>
parents:
44418
diff
changeset
|
445 prefix: NodePrefixRef, |
5ac1eecc9c64
rust-nodemap: core implementation for shortest
Georges Racinet <georges.racinet@octobus.net>
parents:
44418
diff
changeset
|
446 ) -> Result<(Option<Revision>, usize), NodeMapError> { |
5ac1eecc9c64
rust-nodemap: core implementation for shortest
Georges Racinet <georges.racinet@octobus.net>
parents:
44418
diff
changeset
|
447 for (i, visit_item) in self.visit(prefix).enumerate() { |
44261
796d05f3fa84
rust-nodemap: generic NodeTreeVisitor
Georges Racinet <georges.racinet@octobus.net>
parents:
44260
diff
changeset
|
448 if let Some(opt) = visit_item.final_revision() { |
44419
5ac1eecc9c64
rust-nodemap: core implementation for shortest
Georges Racinet <georges.racinet@octobus.net>
parents:
44418
diff
changeset
|
449 return Ok((opt, i + 1)); |
44258
e52401a95b94
rust-nodemap: NodeMap trait with simplest implementation
Georges Racinet <georges.racinet@octobus.net>
parents:
44227
diff
changeset
|
450 } |
e52401a95b94
rust-nodemap: NodeMap trait with simplest implementation
Georges Racinet <georges.racinet@octobus.net>
parents:
44227
diff
changeset
|
451 } |
e52401a95b94
rust-nodemap: NodeMap trait with simplest implementation
Georges Racinet <georges.racinet@octobus.net>
parents:
44227
diff
changeset
|
452 Err(NodeMapError::MultipleResults) |
e52401a95b94
rust-nodemap: NodeMap trait with simplest implementation
Georges Racinet <georges.racinet@octobus.net>
parents:
44227
diff
changeset
|
453 } |
44261
796d05f3fa84
rust-nodemap: generic NodeTreeVisitor
Georges Racinet <georges.racinet@octobus.net>
parents:
44260
diff
changeset
|
454 |
796d05f3fa84
rust-nodemap: generic NodeTreeVisitor
Georges Racinet <georges.racinet@octobus.net>
parents:
44260
diff
changeset
|
455 fn visit<'n, 'p>( |
796d05f3fa84
rust-nodemap: generic NodeTreeVisitor
Georges Racinet <georges.racinet@octobus.net>
parents:
44260
diff
changeset
|
456 &'n self, |
796d05f3fa84
rust-nodemap: generic NodeTreeVisitor
Georges Racinet <georges.racinet@octobus.net>
parents:
44260
diff
changeset
|
457 prefix: NodePrefixRef<'p>, |
796d05f3fa84
rust-nodemap: generic NodeTreeVisitor
Georges Racinet <georges.racinet@octobus.net>
parents:
44260
diff
changeset
|
458 ) -> NodeTreeVisitor<'n, 'p> { |
796d05f3fa84
rust-nodemap: generic NodeTreeVisitor
Georges Racinet <georges.racinet@octobus.net>
parents:
44260
diff
changeset
|
459 NodeTreeVisitor { |
796d05f3fa84
rust-nodemap: generic NodeTreeVisitor
Georges Racinet <georges.racinet@octobus.net>
parents:
44260
diff
changeset
|
460 nt: self, |
44998
26114bd6ec60
rust: do a clippy pass
Rapha?l Gom?s <rgomes@octobus.net>
parents:
44421
diff
changeset
|
461 prefix, |
44261
796d05f3fa84
rust-nodemap: generic NodeTreeVisitor
Georges Racinet <georges.racinet@octobus.net>
parents:
44260
diff
changeset
|
462 visit: self.len() - 1, |
796d05f3fa84
rust-nodemap: generic NodeTreeVisitor
Georges Racinet <georges.racinet@octobus.net>
parents:
44260
diff
changeset
|
463 nybble_idx: 0, |
796d05f3fa84
rust-nodemap: generic NodeTreeVisitor
Georges Racinet <georges.racinet@octobus.net>
parents:
44260
diff
changeset
|
464 done: false, |
796d05f3fa84
rust-nodemap: generic NodeTreeVisitor
Georges Racinet <georges.racinet@octobus.net>
parents:
44260
diff
changeset
|
465 } |
796d05f3fa84
rust-nodemap: generic NodeTreeVisitor
Georges Racinet <georges.racinet@octobus.net>
parents:
44260
diff
changeset
|
466 } |
44390
d2da8667125b
rust-nodemap: insert method
Georges Racinet <georges.racinet@octobus.net>
parents:
44261
diff
changeset
|
467 /// Return a mutable reference for `Block` at index `idx`. |
d2da8667125b
rust-nodemap: insert method
Georges Racinet <georges.racinet@octobus.net>
parents:
44261
diff
changeset
|
468 /// |
d2da8667125b
rust-nodemap: insert method
Georges Racinet <georges.racinet@octobus.net>
parents:
44261
diff
changeset
|
469 /// If `idx` lies in the immutable area, then the reference is to |
d2da8667125b
rust-nodemap: insert method
Georges Racinet <georges.racinet@octobus.net>
parents:
44261
diff
changeset
|
470 /// a newly appended copy. |
d2da8667125b
rust-nodemap: insert method
Georges Racinet <georges.racinet@octobus.net>
parents:
44261
diff
changeset
|
471 /// |
d2da8667125b
rust-nodemap: insert method
Georges Racinet <georges.racinet@octobus.net>
parents:
44261
diff
changeset
|
472 /// Returns (new_idx, glen, mut_ref) where |
d2da8667125b
rust-nodemap: insert method
Georges Racinet <georges.racinet@octobus.net>
parents:
44261
diff
changeset
|
473 /// |
d2da8667125b
rust-nodemap: insert method
Georges Racinet <georges.racinet@octobus.net>
parents:
44261
diff
changeset
|
474 /// - `new_idx` is the index of the mutable `Block` |
d2da8667125b
rust-nodemap: insert method
Georges Racinet <georges.racinet@octobus.net>
parents:
44261
diff
changeset
|
475 /// - `mut_ref` is a mutable reference to the mutable Block. |
d2da8667125b
rust-nodemap: insert method
Georges Racinet <georges.racinet@octobus.net>
parents:
44261
diff
changeset
|
476 /// - `glen` is the new length of `self.growable` |
d2da8667125b
rust-nodemap: insert method
Georges Racinet <georges.racinet@octobus.net>
parents:
44261
diff
changeset
|
477 /// |
d2da8667125b
rust-nodemap: insert method
Georges Racinet <georges.racinet@octobus.net>
parents:
44261
diff
changeset
|
478 /// Note: the caller wouldn't be allowed to query `self.growable.len()` |
d2da8667125b
rust-nodemap: insert method
Georges Racinet <georges.racinet@octobus.net>
parents:
44261
diff
changeset
|
479 /// itself because of the mutable borrow taken with the returned `Block` |
d2da8667125b
rust-nodemap: insert method
Georges Racinet <georges.racinet@octobus.net>
parents:
44261
diff
changeset
|
480 fn mutable_block(&mut self, idx: usize) -> (usize, &mut Block, usize) { |
d2da8667125b
rust-nodemap: insert method
Georges Racinet <georges.racinet@octobus.net>
parents:
44261
diff
changeset
|
481 let ro_blocks = &self.readonly; |
d2da8667125b
rust-nodemap: insert method
Georges Racinet <georges.racinet@octobus.net>
parents:
44261
diff
changeset
|
482 let ro_len = ro_blocks.len(); |
d2da8667125b
rust-nodemap: insert method
Georges Racinet <georges.racinet@octobus.net>
parents:
44261
diff
changeset
|
483 let glen = self.growable.len(); |
d2da8667125b
rust-nodemap: insert method
Georges Racinet <georges.racinet@octobus.net>
parents:
44261
diff
changeset
|
484 if idx < ro_len { |
44420
6329ce04c69f
rust-nodemap: accounting for dead blocks
Georges Racinet <georges.racinet@octobus.net>
parents:
44419
diff
changeset
|
485 self.masked_inner_blocks += 1; |
44998
26114bd6ec60
rust: do a clippy pass
Rapha?l Gom?s <rgomes@octobus.net>
parents:
44421
diff
changeset
|
486 self.growable.push(ro_blocks[idx]); |
44390
d2da8667125b
rust-nodemap: insert method
Georges Racinet <georges.racinet@octobus.net>
parents:
44261
diff
changeset
|
487 (glen + ro_len, &mut self.growable[glen], glen + 1) |
d2da8667125b
rust-nodemap: insert method
Georges Racinet <georges.racinet@octobus.net>
parents:
44261
diff
changeset
|
488 } else if glen + ro_len == idx { |
d2da8667125b
rust-nodemap: insert method
Georges Racinet <georges.racinet@octobus.net>
parents:
44261
diff
changeset
|
489 (idx, &mut self.root, glen) |
d2da8667125b
rust-nodemap: insert method
Georges Racinet <georges.racinet@octobus.net>
parents:
44261
diff
changeset
|
490 } else { |
d2da8667125b
rust-nodemap: insert method
Georges Racinet <georges.racinet@octobus.net>
parents:
44261
diff
changeset
|
491 (idx, &mut self.growable[idx - ro_len], glen) |
d2da8667125b
rust-nodemap: insert method
Georges Racinet <georges.racinet@octobus.net>
parents:
44261
diff
changeset
|
492 } |
d2da8667125b
rust-nodemap: insert method
Georges Racinet <georges.racinet@octobus.net>
parents:
44261
diff
changeset
|
493 } |
d2da8667125b
rust-nodemap: insert method
Georges Racinet <georges.racinet@octobus.net>
parents:
44261
diff
changeset
|
494 |
d2da8667125b
rust-nodemap: insert method
Georges Racinet <georges.racinet@octobus.net>
parents:
44261
diff
changeset
|
495 /// Main insertion method |
d2da8667125b
rust-nodemap: insert method
Georges Racinet <georges.racinet@octobus.net>
parents:
44261
diff
changeset
|
496 /// |
d2da8667125b
rust-nodemap: insert method
Georges Racinet <georges.racinet@octobus.net>
parents:
44261
diff
changeset
|
497 /// This will dive in the node tree to find the deepest `Block` for |
d2da8667125b
rust-nodemap: insert method
Georges Racinet <georges.racinet@octobus.net>
parents:
44261
diff
changeset
|
498 /// `node`, split it as much as needed and record `node` in there. |
d2da8667125b
rust-nodemap: insert method
Georges Racinet <georges.racinet@octobus.net>
parents:
44261
diff
changeset
|
499 /// The method then backtracks, updating references in all the visited |
d2da8667125b
rust-nodemap: insert method
Georges Racinet <georges.racinet@octobus.net>
parents:
44261
diff
changeset
|
500 /// blocks from the root. |
d2da8667125b
rust-nodemap: insert method
Georges Racinet <georges.racinet@octobus.net>
parents:
44261
diff
changeset
|
501 /// |
d2da8667125b
rust-nodemap: insert method
Georges Racinet <georges.racinet@octobus.net>
parents:
44261
diff
changeset
|
502 /// All the mutated `Block` are copied first to the growable part if |
d2da8667125b
rust-nodemap: insert method
Georges Racinet <georges.racinet@octobus.net>
parents:
44261
diff
changeset
|
503 /// needed. That happens for those in the immutable part except the root. |
d2da8667125b
rust-nodemap: insert method
Georges Racinet <georges.racinet@octobus.net>
parents:
44261
diff
changeset
|
504 pub fn insert<I: RevlogIndex>( |
d2da8667125b
rust-nodemap: insert method
Georges Racinet <georges.racinet@octobus.net>
parents:
44261
diff
changeset
|
505 &mut self, |
d2da8667125b
rust-nodemap: insert method
Georges Racinet <georges.racinet@octobus.net>
parents:
44261
diff
changeset
|
506 index: &I, |
d2da8667125b
rust-nodemap: insert method
Georges Racinet <georges.racinet@octobus.net>
parents:
44261
diff
changeset
|
507 node: &Node, |
d2da8667125b
rust-nodemap: insert method
Georges Racinet <georges.racinet@octobus.net>
parents:
44261
diff
changeset
|
508 rev: Revision, |
d2da8667125b
rust-nodemap: insert method
Georges Racinet <georges.racinet@octobus.net>
parents:
44261
diff
changeset
|
509 ) -> Result<(), NodeMapError> { |
d2da8667125b
rust-nodemap: insert method
Georges Racinet <georges.racinet@octobus.net>
parents:
44261
diff
changeset
|
510 let ro_len = &self.readonly.len(); |
d2da8667125b
rust-nodemap: insert method
Georges Racinet <georges.racinet@octobus.net>
parents:
44261
diff
changeset
|
511 |
d2da8667125b
rust-nodemap: insert method
Georges Racinet <georges.racinet@octobus.net>
parents:
44261
diff
changeset
|
512 let mut visit_steps: Vec<_> = self.visit(node.into()).collect(); |
d2da8667125b
rust-nodemap: insert method
Georges Racinet <georges.racinet@octobus.net>
parents:
44261
diff
changeset
|
513 let read_nybbles = visit_steps.len(); |
d2da8667125b
rust-nodemap: insert method
Georges Racinet <georges.racinet@octobus.net>
parents:
44261
diff
changeset
|
514 // visit_steps cannot be empty, since we always visit the root block |
d2da8667125b
rust-nodemap: insert method
Georges Racinet <georges.racinet@octobus.net>
parents:
44261
diff
changeset
|
515 let deepest = visit_steps.pop().unwrap(); |
d2da8667125b
rust-nodemap: insert method
Georges Racinet <georges.racinet@octobus.net>
parents:
44261
diff
changeset
|
516 |
d2da8667125b
rust-nodemap: insert method
Georges Racinet <georges.racinet@octobus.net>
parents:
44261
diff
changeset
|
517 let (mut block_idx, mut block, mut glen) = |
d2da8667125b
rust-nodemap: insert method
Georges Racinet <georges.racinet@octobus.net>
parents:
44261
diff
changeset
|
518 self.mutable_block(deepest.block_idx); |
d2da8667125b
rust-nodemap: insert method
Georges Racinet <georges.racinet@octobus.net>
parents:
44261
diff
changeset
|
519 |
d2da8667125b
rust-nodemap: insert method
Georges Racinet <georges.racinet@octobus.net>
parents:
44261
diff
changeset
|
520 if let Element::Rev(old_rev) = deepest.element { |
d2da8667125b
rust-nodemap: insert method
Georges Racinet <georges.racinet@octobus.net>
parents:
44261
diff
changeset
|
521 let old_node = index |
d2da8667125b
rust-nodemap: insert method
Georges Racinet <georges.racinet@octobus.net>
parents:
44261
diff
changeset
|
522 .node(old_rev) |
d2da8667125b
rust-nodemap: insert method
Georges Racinet <georges.racinet@octobus.net>
parents:
44261
diff
changeset
|
523 .ok_or_else(|| NodeMapError::RevisionNotInIndex(old_rev))?; |
d2da8667125b
rust-nodemap: insert method
Georges Racinet <georges.racinet@octobus.net>
parents:
44261
diff
changeset
|
524 if old_node == node { |
d2da8667125b
rust-nodemap: insert method
Georges Racinet <georges.racinet@octobus.net>
parents:
44261
diff
changeset
|
525 return Ok(()); // avoid creating lots of useless blocks |
d2da8667125b
rust-nodemap: insert method
Georges Racinet <georges.racinet@octobus.net>
parents:
44261
diff
changeset
|
526 } |
d2da8667125b
rust-nodemap: insert method
Georges Racinet <georges.racinet@octobus.net>
parents:
44261
diff
changeset
|
527 |
d2da8667125b
rust-nodemap: insert method
Georges Racinet <georges.racinet@octobus.net>
parents:
44261
diff
changeset
|
528 // Looping over the tail of nybbles in both nodes, creating |
d2da8667125b
rust-nodemap: insert method
Georges Racinet <georges.racinet@octobus.net>
parents:
44261
diff
changeset
|
529 // new blocks until we find the difference |
d2da8667125b
rust-nodemap: insert method
Georges Racinet <georges.racinet@octobus.net>
parents:
44261
diff
changeset
|
530 let mut new_block_idx = ro_len + glen; |
d2da8667125b
rust-nodemap: insert method
Georges Racinet <georges.racinet@octobus.net>
parents:
44261
diff
changeset
|
531 let mut nybble = deepest.nybble; |
d2da8667125b
rust-nodemap: insert method
Georges Racinet <georges.racinet@octobus.net>
parents:
44261
diff
changeset
|
532 for nybble_pos in read_nybbles..node.nybbles_len() { |
d2da8667125b
rust-nodemap: insert method
Georges Racinet <georges.racinet@octobus.net>
parents:
44261
diff
changeset
|
533 block.set(nybble, Element::Block(new_block_idx)); |
d2da8667125b
rust-nodemap: insert method
Georges Racinet <georges.racinet@octobus.net>
parents:
44261
diff
changeset
|
534 |
d2da8667125b
rust-nodemap: insert method
Georges Racinet <georges.racinet@octobus.net>
parents:
44261
diff
changeset
|
535 let new_nybble = node.get_nybble(nybble_pos); |
d2da8667125b
rust-nodemap: insert method
Georges Racinet <georges.racinet@octobus.net>
parents:
44261
diff
changeset
|
536 let old_nybble = old_node.get_nybble(nybble_pos); |
d2da8667125b
rust-nodemap: insert method
Georges Racinet <georges.racinet@octobus.net>
parents:
44261
diff
changeset
|
537 |
d2da8667125b
rust-nodemap: insert method
Georges Racinet <georges.racinet@octobus.net>
parents:
44261
diff
changeset
|
538 if old_nybble == new_nybble { |
d2da8667125b
rust-nodemap: insert method
Georges Racinet <georges.racinet@octobus.net>
parents:
44261
diff
changeset
|
539 self.growable.push(Block::new()); |
d2da8667125b
rust-nodemap: insert method
Georges Racinet <georges.racinet@octobus.net>
parents:
44261
diff
changeset
|
540 block = &mut self.growable[glen]; |
d2da8667125b
rust-nodemap: insert method
Georges Racinet <georges.racinet@octobus.net>
parents:
44261
diff
changeset
|
541 glen += 1; |
d2da8667125b
rust-nodemap: insert method
Georges Racinet <georges.racinet@octobus.net>
parents:
44261
diff
changeset
|
542 new_block_idx += 1; |
d2da8667125b
rust-nodemap: insert method
Georges Racinet <georges.racinet@octobus.net>
parents:
44261
diff
changeset
|
543 nybble = new_nybble; |
d2da8667125b
rust-nodemap: insert method
Georges Racinet <georges.racinet@octobus.net>
parents:
44261
diff
changeset
|
544 } else { |
d2da8667125b
rust-nodemap: insert method
Georges Racinet <georges.racinet@octobus.net>
parents:
44261
diff
changeset
|
545 let mut new_block = Block::new(); |
d2da8667125b
rust-nodemap: insert method
Georges Racinet <georges.racinet@octobus.net>
parents:
44261
diff
changeset
|
546 new_block.set(old_nybble, Element::Rev(old_rev)); |
d2da8667125b
rust-nodemap: insert method
Georges Racinet <georges.racinet@octobus.net>
parents:
44261
diff
changeset
|
547 new_block.set(new_nybble, Element::Rev(rev)); |
d2da8667125b
rust-nodemap: insert method
Georges Racinet <georges.racinet@octobus.net>
parents:
44261
diff
changeset
|
548 self.growable.push(new_block); |
d2da8667125b
rust-nodemap: insert method
Georges Racinet <georges.racinet@octobus.net>
parents:
44261
diff
changeset
|
549 break; |
d2da8667125b
rust-nodemap: insert method
Georges Racinet <georges.racinet@octobus.net>
parents:
44261
diff
changeset
|
550 } |
d2da8667125b
rust-nodemap: insert method
Georges Racinet <georges.racinet@octobus.net>
parents:
44261
diff
changeset
|
551 } |
d2da8667125b
rust-nodemap: insert method
Georges Racinet <georges.racinet@octobus.net>
parents:
44261
diff
changeset
|
552 } else { |
d2da8667125b
rust-nodemap: insert method
Georges Racinet <georges.racinet@octobus.net>
parents:
44261
diff
changeset
|
553 // Free slot in the deepest block: no splitting has to be done |
d2da8667125b
rust-nodemap: insert method
Georges Racinet <georges.racinet@octobus.net>
parents:
44261
diff
changeset
|
554 block.set(deepest.nybble, Element::Rev(rev)); |
d2da8667125b
rust-nodemap: insert method
Georges Racinet <georges.racinet@octobus.net>
parents:
44261
diff
changeset
|
555 } |
d2da8667125b
rust-nodemap: insert method
Georges Racinet <georges.racinet@octobus.net>
parents:
44261
diff
changeset
|
556 |
d2da8667125b
rust-nodemap: insert method
Georges Racinet <georges.racinet@octobus.net>
parents:
44261
diff
changeset
|
557 // Backtrack over visit steps to update references |
d2da8667125b
rust-nodemap: insert method
Georges Racinet <georges.racinet@octobus.net>
parents:
44261
diff
changeset
|
558 while let Some(visited) = visit_steps.pop() { |
d2da8667125b
rust-nodemap: insert method
Georges Racinet <georges.racinet@octobus.net>
parents:
44261
diff
changeset
|
559 let to_write = Element::Block(block_idx); |
d2da8667125b
rust-nodemap: insert method
Georges Racinet <georges.racinet@octobus.net>
parents:
44261
diff
changeset
|
560 if visit_steps.is_empty() { |
d2da8667125b
rust-nodemap: insert method
Georges Racinet <georges.racinet@octobus.net>
parents:
44261
diff
changeset
|
561 self.root.set(visited.nybble, to_write); |
d2da8667125b
rust-nodemap: insert method
Georges Racinet <georges.racinet@octobus.net>
parents:
44261
diff
changeset
|
562 break; |
d2da8667125b
rust-nodemap: insert method
Georges Racinet <georges.racinet@octobus.net>
parents:
44261
diff
changeset
|
563 } |
d2da8667125b
rust-nodemap: insert method
Georges Racinet <georges.racinet@octobus.net>
parents:
44261
diff
changeset
|
564 let (new_idx, block, _) = self.mutable_block(visited.block_idx); |
d2da8667125b
rust-nodemap: insert method
Georges Racinet <georges.racinet@octobus.net>
parents:
44261
diff
changeset
|
565 if block.get(visited.nybble) == to_write { |
d2da8667125b
rust-nodemap: insert method
Georges Racinet <georges.racinet@octobus.net>
parents:
44261
diff
changeset
|
566 break; |
d2da8667125b
rust-nodemap: insert method
Georges Racinet <georges.racinet@octobus.net>
parents:
44261
diff
changeset
|
567 } |
d2da8667125b
rust-nodemap: insert method
Georges Racinet <georges.racinet@octobus.net>
parents:
44261
diff
changeset
|
568 block.set(visited.nybble, to_write); |
d2da8667125b
rust-nodemap: insert method
Georges Racinet <georges.racinet@octobus.net>
parents:
44261
diff
changeset
|
569 block_idx = new_idx; |
d2da8667125b
rust-nodemap: insert method
Georges Racinet <georges.racinet@octobus.net>
parents:
44261
diff
changeset
|
570 } |
d2da8667125b
rust-nodemap: insert method
Georges Racinet <georges.racinet@octobus.net>
parents:
44261
diff
changeset
|
571 Ok(()) |
d2da8667125b
rust-nodemap: insert method
Georges Racinet <georges.racinet@octobus.net>
parents:
44261
diff
changeset
|
572 } |
44420
6329ce04c69f
rust-nodemap: accounting for dead blocks
Georges Racinet <georges.racinet@octobus.net>
parents:
44419
diff
changeset
|
573 |
44421
d518994384a4
rust-nodemap: a method for full invalidation
Georges Racinet <georges.racinet@octobus.net>
parents:
44420
diff
changeset
|
574 /// Make the whole `NodeTree` logically empty, without touching the |
d518994384a4
rust-nodemap: a method for full invalidation
Georges Racinet <georges.racinet@octobus.net>
parents:
44420
diff
changeset
|
575 /// immutable part. |
d518994384a4
rust-nodemap: a method for full invalidation
Georges Racinet <georges.racinet@octobus.net>
parents:
44420
diff
changeset
|
576 pub fn invalidate_all(&mut self) { |
d518994384a4
rust-nodemap: a method for full invalidation
Georges Racinet <georges.racinet@octobus.net>
parents:
44420
diff
changeset
|
577 self.root = Block::new(); |
d518994384a4
rust-nodemap: a method for full invalidation
Georges Racinet <georges.racinet@octobus.net>
parents:
44420
diff
changeset
|
578 self.growable = Vec::new(); |
d518994384a4
rust-nodemap: a method for full invalidation
Georges Racinet <georges.racinet@octobus.net>
parents:
44420
diff
changeset
|
579 self.masked_inner_blocks = self.readonly.len(); |
d518994384a4
rust-nodemap: a method for full invalidation
Georges Racinet <georges.racinet@octobus.net>
parents:
44420
diff
changeset
|
580 } |
d518994384a4
rust-nodemap: a method for full invalidation
Georges Racinet <georges.racinet@octobus.net>
parents:
44420
diff
changeset
|
581 |
44420
6329ce04c69f
rust-nodemap: accounting for dead blocks
Georges Racinet <georges.racinet@octobus.net>
parents:
44419
diff
changeset
|
582 /// Return the number of blocks in the readonly part that are currently |
6329ce04c69f
rust-nodemap: accounting for dead blocks
Georges Racinet <georges.racinet@octobus.net>
parents:
44419
diff
changeset
|
583 /// masked in the mutable part. |
6329ce04c69f
rust-nodemap: accounting for dead blocks
Georges Racinet <georges.racinet@octobus.net>
parents:
44419
diff
changeset
|
584 /// |
6329ce04c69f
rust-nodemap: accounting for dead blocks
Georges Racinet <georges.racinet@octobus.net>
parents:
44419
diff
changeset
|
585 /// The `NodeTree` structure has no efficient way to know how many blocks |
6329ce04c69f
rust-nodemap: accounting for dead blocks
Georges Racinet <georges.racinet@octobus.net>
parents:
44419
diff
changeset
|
586 /// are already unreachable in the readonly part. |
44421
d518994384a4
rust-nodemap: a method for full invalidation
Georges Racinet <georges.racinet@octobus.net>
parents:
44420
diff
changeset
|
587 /// |
d518994384a4
rust-nodemap: a method for full invalidation
Georges Racinet <georges.racinet@octobus.net>
parents:
44420
diff
changeset
|
588 /// After a call to `invalidate_all()`, the returned number can be actually |
d518994384a4
rust-nodemap: a method for full invalidation
Georges Racinet <georges.racinet@octobus.net>
parents:
44420
diff
changeset
|
589 /// bigger than the whole readonly part, a conventional way to mean that |
d518994384a4
rust-nodemap: a method for full invalidation
Georges Racinet <georges.racinet@octobus.net>
parents:
44420
diff
changeset
|
590 /// all the readonly blocks have been masked. This is what is really |
d518994384a4
rust-nodemap: a method for full invalidation
Georges Racinet <georges.racinet@octobus.net>
parents:
44420
diff
changeset
|
591 /// useful to the caller and does not require to know how many were |
d518994384a4
rust-nodemap: a method for full invalidation
Georges Racinet <georges.racinet@octobus.net>
parents:
44420
diff
changeset
|
592 /// actually unreachable to begin with. |
44420
6329ce04c69f
rust-nodemap: accounting for dead blocks
Georges Racinet <georges.racinet@octobus.net>
parents:
44419
diff
changeset
|
593 pub fn masked_readonly_blocks(&self) -> usize { |
6329ce04c69f
rust-nodemap: accounting for dead blocks
Georges Racinet <georges.racinet@octobus.net>
parents:
44419
diff
changeset
|
594 if let Some(readonly_root) = self.readonly.last() { |
6329ce04c69f
rust-nodemap: accounting for dead blocks
Georges Racinet <georges.racinet@octobus.net>
parents:
44419
diff
changeset
|
595 if readonly_root == &self.root { |
6329ce04c69f
rust-nodemap: accounting for dead blocks
Georges Racinet <georges.racinet@octobus.net>
parents:
44419
diff
changeset
|
596 return 0; |
6329ce04c69f
rust-nodemap: accounting for dead blocks
Georges Racinet <georges.racinet@octobus.net>
parents:
44419
diff
changeset
|
597 } |
6329ce04c69f
rust-nodemap: accounting for dead blocks
Georges Racinet <georges.racinet@octobus.net>
parents:
44419
diff
changeset
|
598 } else { |
6329ce04c69f
rust-nodemap: accounting for dead blocks
Georges Racinet <georges.racinet@octobus.net>
parents:
44419
diff
changeset
|
599 return 0; |
6329ce04c69f
rust-nodemap: accounting for dead blocks
Georges Racinet <georges.racinet@octobus.net>
parents:
44419
diff
changeset
|
600 } |
6329ce04c69f
rust-nodemap: accounting for dead blocks
Georges Racinet <georges.racinet@octobus.net>
parents:
44419
diff
changeset
|
601 self.masked_inner_blocks + 1 |
6329ce04c69f
rust-nodemap: accounting for dead blocks
Georges Racinet <georges.racinet@octobus.net>
parents:
44419
diff
changeset
|
602 } |
44261
796d05f3fa84
rust-nodemap: generic NodeTreeVisitor
Georges Racinet <georges.racinet@octobus.net>
parents:
44260
diff
changeset
|
603 } |
796d05f3fa84
rust-nodemap: generic NodeTreeVisitor
Georges Racinet <georges.racinet@octobus.net>
parents:
44260
diff
changeset
|
604 |
44416
a98ba6983a63
rust-nodemap: input/output primitives
Georges Racinet <georges.racinet@octobus.net>
parents:
44390
diff
changeset
|
605 pub struct NodeTreeBytes { |
a98ba6983a63
rust-nodemap: input/output primitives
Georges Racinet <georges.racinet@octobus.net>
parents:
44390
diff
changeset
|
606 buffer: Box<dyn Deref<Target = [u8]> + Send>, |
a98ba6983a63
rust-nodemap: input/output primitives
Georges Racinet <georges.racinet@octobus.net>
parents:
44390
diff
changeset
|
607 len_in_blocks: usize, |
a98ba6983a63
rust-nodemap: input/output primitives
Georges Racinet <georges.racinet@octobus.net>
parents:
44390
diff
changeset
|
608 } |
a98ba6983a63
rust-nodemap: input/output primitives
Georges Racinet <georges.racinet@octobus.net>
parents:
44390
diff
changeset
|
609 |
a98ba6983a63
rust-nodemap: input/output primitives
Georges Racinet <georges.racinet@octobus.net>
parents:
44390
diff
changeset
|
610 impl NodeTreeBytes { |
a98ba6983a63
rust-nodemap: input/output primitives
Georges Racinet <georges.racinet@octobus.net>
parents:
44390
diff
changeset
|
611 fn new( |
a98ba6983a63
rust-nodemap: input/output primitives
Georges Racinet <georges.racinet@octobus.net>
parents:
44390
diff
changeset
|
612 buffer: Box<dyn Deref<Target = [u8]> + Send>, |
a98ba6983a63
rust-nodemap: input/output primitives
Georges Racinet <georges.racinet@octobus.net>
parents:
44390
diff
changeset
|
613 amount: usize, |
a98ba6983a63
rust-nodemap: input/output primitives
Georges Racinet <georges.racinet@octobus.net>
parents:
44390
diff
changeset
|
614 ) -> Self { |
a98ba6983a63
rust-nodemap: input/output primitives
Georges Racinet <georges.racinet@octobus.net>
parents:
44390
diff
changeset
|
615 assert!(buffer.len() >= amount); |
a98ba6983a63
rust-nodemap: input/output primitives
Georges Racinet <georges.racinet@octobus.net>
parents:
44390
diff
changeset
|
616 let len_in_blocks = amount / BLOCK_SIZE; |
a98ba6983a63
rust-nodemap: input/output primitives
Georges Racinet <georges.racinet@octobus.net>
parents:
44390
diff
changeset
|
617 NodeTreeBytes { |
a98ba6983a63
rust-nodemap: input/output primitives
Georges Racinet <georges.racinet@octobus.net>
parents:
44390
diff
changeset
|
618 buffer, |
a98ba6983a63
rust-nodemap: input/output primitives
Georges Racinet <georges.racinet@octobus.net>
parents:
44390
diff
changeset
|
619 len_in_blocks, |
a98ba6983a63
rust-nodemap: input/output primitives
Georges Racinet <georges.racinet@octobus.net>
parents:
44390
diff
changeset
|
620 } |
a98ba6983a63
rust-nodemap: input/output primitives
Georges Racinet <georges.racinet@octobus.net>
parents:
44390
diff
changeset
|
621 } |
a98ba6983a63
rust-nodemap: input/output primitives
Georges Racinet <georges.racinet@octobus.net>
parents:
44390
diff
changeset
|
622 } |
a98ba6983a63
rust-nodemap: input/output primitives
Georges Racinet <georges.racinet@octobus.net>
parents:
44390
diff
changeset
|
623 |
a98ba6983a63
rust-nodemap: input/output primitives
Georges Racinet <georges.racinet@octobus.net>
parents:
44390
diff
changeset
|
624 impl Deref for NodeTreeBytes { |
a98ba6983a63
rust-nodemap: input/output primitives
Georges Racinet <georges.racinet@octobus.net>
parents:
44390
diff
changeset
|
625 type Target = [Block]; |
a98ba6983a63
rust-nodemap: input/output primitives
Georges Racinet <georges.racinet@octobus.net>
parents:
44390
diff
changeset
|
626 |
a98ba6983a63
rust-nodemap: input/output primitives
Georges Racinet <georges.racinet@octobus.net>
parents:
44390
diff
changeset
|
627 fn deref(&self) -> &[Block] { |
a98ba6983a63
rust-nodemap: input/output primitives
Georges Racinet <georges.racinet@octobus.net>
parents:
44390
diff
changeset
|
628 unsafe { |
a98ba6983a63
rust-nodemap: input/output primitives
Georges Racinet <georges.racinet@octobus.net>
parents:
44390
diff
changeset
|
629 slice::from_raw_parts( |
a98ba6983a63
rust-nodemap: input/output primitives
Georges Racinet <georges.racinet@octobus.net>
parents:
44390
diff
changeset
|
630 (&self.buffer).as_ptr() as *const Block, |
a98ba6983a63
rust-nodemap: input/output primitives
Georges Racinet <georges.racinet@octobus.net>
parents:
44390
diff
changeset
|
631 self.len_in_blocks, |
a98ba6983a63
rust-nodemap: input/output primitives
Georges Racinet <georges.racinet@octobus.net>
parents:
44390
diff
changeset
|
632 ) |
a98ba6983a63
rust-nodemap: input/output primitives
Georges Racinet <georges.racinet@octobus.net>
parents:
44390
diff
changeset
|
633 } |
a98ba6983a63
rust-nodemap: input/output primitives
Georges Racinet <georges.racinet@octobus.net>
parents:
44390
diff
changeset
|
634 } |
a98ba6983a63
rust-nodemap: input/output primitives
Georges Racinet <georges.racinet@octobus.net>
parents:
44390
diff
changeset
|
635 } |
a98ba6983a63
rust-nodemap: input/output primitives
Georges Racinet <georges.racinet@octobus.net>
parents:
44390
diff
changeset
|
636 |
44261
796d05f3fa84
rust-nodemap: generic NodeTreeVisitor
Georges Racinet <georges.racinet@octobus.net>
parents:
44260
diff
changeset
|
637 struct NodeTreeVisitor<'n, 'p> { |
796d05f3fa84
rust-nodemap: generic NodeTreeVisitor
Georges Racinet <georges.racinet@octobus.net>
parents:
44260
diff
changeset
|
638 nt: &'n NodeTree, |
796d05f3fa84
rust-nodemap: generic NodeTreeVisitor
Georges Racinet <georges.racinet@octobus.net>
parents:
44260
diff
changeset
|
639 prefix: NodePrefixRef<'p>, |
796d05f3fa84
rust-nodemap: generic NodeTreeVisitor
Georges Racinet <georges.racinet@octobus.net>
parents:
44260
diff
changeset
|
640 visit: usize, |
796d05f3fa84
rust-nodemap: generic NodeTreeVisitor
Georges Racinet <georges.racinet@octobus.net>
parents:
44260
diff
changeset
|
641 nybble_idx: usize, |
796d05f3fa84
rust-nodemap: generic NodeTreeVisitor
Georges Racinet <georges.racinet@octobus.net>
parents:
44260
diff
changeset
|
642 done: bool, |
796d05f3fa84
rust-nodemap: generic NodeTreeVisitor
Georges Racinet <georges.racinet@octobus.net>
parents:
44260
diff
changeset
|
643 } |
796d05f3fa84
rust-nodemap: generic NodeTreeVisitor
Georges Racinet <georges.racinet@octobus.net>
parents:
44260
diff
changeset
|
644 |
796d05f3fa84
rust-nodemap: generic NodeTreeVisitor
Georges Racinet <georges.racinet@octobus.net>
parents:
44260
diff
changeset
|
645 #[derive(Debug, PartialEq, Clone)] |
796d05f3fa84
rust-nodemap: generic NodeTreeVisitor
Georges Racinet <georges.racinet@octobus.net>
parents:
44260
diff
changeset
|
646 struct NodeTreeVisitItem { |
796d05f3fa84
rust-nodemap: generic NodeTreeVisitor
Georges Racinet <georges.racinet@octobus.net>
parents:
44260
diff
changeset
|
647 block_idx: usize, |
796d05f3fa84
rust-nodemap: generic NodeTreeVisitor
Georges Racinet <georges.racinet@octobus.net>
parents:
44260
diff
changeset
|
648 nybble: u8, |
796d05f3fa84
rust-nodemap: generic NodeTreeVisitor
Georges Racinet <georges.racinet@octobus.net>
parents:
44260
diff
changeset
|
649 element: Element, |
796d05f3fa84
rust-nodemap: generic NodeTreeVisitor
Georges Racinet <georges.racinet@octobus.net>
parents:
44260
diff
changeset
|
650 } |
796d05f3fa84
rust-nodemap: generic NodeTreeVisitor
Georges Racinet <georges.racinet@octobus.net>
parents:
44260
diff
changeset
|
651 |
796d05f3fa84
rust-nodemap: generic NodeTreeVisitor
Georges Racinet <georges.racinet@octobus.net>
parents:
44260
diff
changeset
|
652 impl<'n, 'p> Iterator for NodeTreeVisitor<'n, 'p> { |
796d05f3fa84
rust-nodemap: generic NodeTreeVisitor
Georges Racinet <georges.racinet@octobus.net>
parents:
44260
diff
changeset
|
653 type Item = NodeTreeVisitItem; |
796d05f3fa84
rust-nodemap: generic NodeTreeVisitor
Georges Racinet <georges.racinet@octobus.net>
parents:
44260
diff
changeset
|
654 |
796d05f3fa84
rust-nodemap: generic NodeTreeVisitor
Georges Racinet <georges.racinet@octobus.net>
parents:
44260
diff
changeset
|
655 fn next(&mut self) -> Option<Self::Item> { |
796d05f3fa84
rust-nodemap: generic NodeTreeVisitor
Georges Racinet <georges.racinet@octobus.net>
parents:
44260
diff
changeset
|
656 if self.done || self.nybble_idx >= self.prefix.len() { |
796d05f3fa84
rust-nodemap: generic NodeTreeVisitor
Georges Racinet <georges.racinet@octobus.net>
parents:
44260
diff
changeset
|
657 return None; |
796d05f3fa84
rust-nodemap: generic NodeTreeVisitor
Georges Racinet <georges.racinet@octobus.net>
parents:
44260
diff
changeset
|
658 } |
796d05f3fa84
rust-nodemap: generic NodeTreeVisitor
Georges Racinet <georges.racinet@octobus.net>
parents:
44260
diff
changeset
|
659 |
796d05f3fa84
rust-nodemap: generic NodeTreeVisitor
Georges Racinet <georges.racinet@octobus.net>
parents:
44260
diff
changeset
|
660 let nybble = self.prefix.get_nybble(self.nybble_idx); |
796d05f3fa84
rust-nodemap: generic NodeTreeVisitor
Georges Racinet <georges.racinet@octobus.net>
parents:
44260
diff
changeset
|
661 self.nybble_idx += 1; |
796d05f3fa84
rust-nodemap: generic NodeTreeVisitor
Georges Racinet <georges.racinet@octobus.net>
parents:
44260
diff
changeset
|
662 |
796d05f3fa84
rust-nodemap: generic NodeTreeVisitor
Georges Racinet <georges.racinet@octobus.net>
parents:
44260
diff
changeset
|
663 let visit = self.visit; |
796d05f3fa84
rust-nodemap: generic NodeTreeVisitor
Georges Racinet <georges.racinet@octobus.net>
parents:
44260
diff
changeset
|
664 let element = self.nt[visit].get(nybble); |
796d05f3fa84
rust-nodemap: generic NodeTreeVisitor
Georges Racinet <georges.racinet@octobus.net>
parents:
44260
diff
changeset
|
665 if let Element::Block(idx) = element { |
796d05f3fa84
rust-nodemap: generic NodeTreeVisitor
Georges Racinet <georges.racinet@octobus.net>
parents:
44260
diff
changeset
|
666 self.visit = idx; |
796d05f3fa84
rust-nodemap: generic NodeTreeVisitor
Georges Racinet <georges.racinet@octobus.net>
parents:
44260
diff
changeset
|
667 } else { |
796d05f3fa84
rust-nodemap: generic NodeTreeVisitor
Georges Racinet <georges.racinet@octobus.net>
parents:
44260
diff
changeset
|
668 self.done = true; |
796d05f3fa84
rust-nodemap: generic NodeTreeVisitor
Georges Racinet <georges.racinet@octobus.net>
parents:
44260
diff
changeset
|
669 } |
796d05f3fa84
rust-nodemap: generic NodeTreeVisitor
Georges Racinet <georges.racinet@octobus.net>
parents:
44260
diff
changeset
|
670 |
796d05f3fa84
rust-nodemap: generic NodeTreeVisitor
Georges Racinet <georges.racinet@octobus.net>
parents:
44260
diff
changeset
|
671 Some(NodeTreeVisitItem { |
796d05f3fa84
rust-nodemap: generic NodeTreeVisitor
Georges Racinet <georges.racinet@octobus.net>
parents:
44260
diff
changeset
|
672 block_idx: visit, |
44998
26114bd6ec60
rust: do a clippy pass
Rapha?l Gom?s <rgomes@octobus.net>
parents:
44421
diff
changeset
|
673 nybble, |
26114bd6ec60
rust: do a clippy pass
Rapha?l Gom?s <rgomes@octobus.net>
parents:
44421
diff
changeset
|
674 element, |
44261
796d05f3fa84
rust-nodemap: generic NodeTreeVisitor
Georges Racinet <georges.racinet@octobus.net>
parents:
44260
diff
changeset
|
675 }) |
796d05f3fa84
rust-nodemap: generic NodeTreeVisitor
Georges Racinet <georges.racinet@octobus.net>
parents:
44260
diff
changeset
|
676 } |
796d05f3fa84
rust-nodemap: generic NodeTreeVisitor
Georges Racinet <georges.racinet@octobus.net>
parents:
44260
diff
changeset
|
677 } |
796d05f3fa84
rust-nodemap: generic NodeTreeVisitor
Georges Racinet <georges.racinet@octobus.net>
parents:
44260
diff
changeset
|
678 |
796d05f3fa84
rust-nodemap: generic NodeTreeVisitor
Georges Racinet <georges.racinet@octobus.net>
parents:
44260
diff
changeset
|
679 impl NodeTreeVisitItem { |
796d05f3fa84
rust-nodemap: generic NodeTreeVisitor
Georges Racinet <georges.racinet@octobus.net>
parents:
44260
diff
changeset
|
680 // Return `Some(opt)` if this item is final, with `opt` being the |
796d05f3fa84
rust-nodemap: generic NodeTreeVisitor
Georges Racinet <georges.racinet@octobus.net>
parents:
44260
diff
changeset
|
681 // `Revision` that it may represent. |
796d05f3fa84
rust-nodemap: generic NodeTreeVisitor
Georges Racinet <georges.racinet@octobus.net>
parents:
44260
diff
changeset
|
682 // |
796d05f3fa84
rust-nodemap: generic NodeTreeVisitor
Georges Racinet <georges.racinet@octobus.net>
parents:
44260
diff
changeset
|
683 // If the item is not terminal, return `None` |
796d05f3fa84
rust-nodemap: generic NodeTreeVisitor
Georges Racinet <georges.racinet@octobus.net>
parents:
44260
diff
changeset
|
684 fn final_revision(&self) -> Option<Option<Revision>> { |
796d05f3fa84
rust-nodemap: generic NodeTreeVisitor
Georges Racinet <georges.racinet@octobus.net>
parents:
44260
diff
changeset
|
685 match self.element { |
796d05f3fa84
rust-nodemap: generic NodeTreeVisitor
Georges Racinet <georges.racinet@octobus.net>
parents:
44260
diff
changeset
|
686 Element::Block(_) => None, |
796d05f3fa84
rust-nodemap: generic NodeTreeVisitor
Georges Racinet <georges.racinet@octobus.net>
parents:
44260
diff
changeset
|
687 Element::Rev(r) => Some(Some(r)), |
796d05f3fa84
rust-nodemap: generic NodeTreeVisitor
Georges Racinet <georges.racinet@octobus.net>
parents:
44260
diff
changeset
|
688 Element::None => Some(None), |
796d05f3fa84
rust-nodemap: generic NodeTreeVisitor
Georges Racinet <georges.racinet@octobus.net>
parents:
44260
diff
changeset
|
689 } |
796d05f3fa84
rust-nodemap: generic NodeTreeVisitor
Georges Racinet <georges.racinet@octobus.net>
parents:
44260
diff
changeset
|
690 } |
44258
e52401a95b94
rust-nodemap: NodeMap trait with simplest implementation
Georges Racinet <georges.racinet@octobus.net>
parents:
44227
diff
changeset
|
691 } |
e52401a95b94
rust-nodemap: NodeMap trait with simplest implementation
Georges Racinet <georges.racinet@octobus.net>
parents:
44227
diff
changeset
|
692 |
e52401a95b94
rust-nodemap: NodeMap trait with simplest implementation
Georges Racinet <georges.racinet@octobus.net>
parents:
44227
diff
changeset
|
693 impl From<Vec<Block>> for NodeTree { |
e52401a95b94
rust-nodemap: NodeMap trait with simplest implementation
Georges Racinet <georges.racinet@octobus.net>
parents:
44227
diff
changeset
|
694 fn from(vec: Vec<Block>) -> Self { |
44260
a19331456d48
rust-nodemap: mutable NodeTree data structure
Georges Racinet <georges.racinet@octobus.net>
parents:
44259
diff
changeset
|
695 Self::new(Box::new(vec)) |
44258
e52401a95b94
rust-nodemap: NodeMap trait with simplest implementation
Georges Racinet <georges.racinet@octobus.net>
parents:
44227
diff
changeset
|
696 } |
e52401a95b94
rust-nodemap: NodeMap trait with simplest implementation
Georges Racinet <georges.racinet@octobus.net>
parents:
44227
diff
changeset
|
697 } |
e52401a95b94
rust-nodemap: NodeMap trait with simplest implementation
Georges Racinet <georges.racinet@octobus.net>
parents:
44227
diff
changeset
|
698 |
e52401a95b94
rust-nodemap: NodeMap trait with simplest implementation
Georges Racinet <georges.racinet@octobus.net>
parents:
44227
diff
changeset
|
699 impl fmt::Debug for NodeTree { |
e52401a95b94
rust-nodemap: NodeMap trait with simplest implementation
Georges Racinet <georges.racinet@octobus.net>
parents:
44227
diff
changeset
|
700 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { |
44260
a19331456d48
rust-nodemap: mutable NodeTree data structure
Georges Racinet <georges.racinet@octobus.net>
parents:
44259
diff
changeset
|
701 let readonly: &[Block] = &*self.readonly; |
a19331456d48
rust-nodemap: mutable NodeTree data structure
Georges Racinet <georges.racinet@octobus.net>
parents:
44259
diff
changeset
|
702 write!( |
a19331456d48
rust-nodemap: mutable NodeTree data structure
Georges Racinet <georges.racinet@octobus.net>
parents:
44259
diff
changeset
|
703 f, |
a19331456d48
rust-nodemap: mutable NodeTree data structure
Georges Racinet <georges.racinet@octobus.net>
parents:
44259
diff
changeset
|
704 "readonly: {:?}, growable: {:?}, root: {:?}", |
a19331456d48
rust-nodemap: mutable NodeTree data structure
Georges Racinet <georges.racinet@octobus.net>
parents:
44259
diff
changeset
|
705 readonly, self.growable, self.root |
a19331456d48
rust-nodemap: mutable NodeTree data structure
Georges Racinet <georges.racinet@octobus.net>
parents:
44259
diff
changeset
|
706 ) |
44258
e52401a95b94
rust-nodemap: NodeMap trait with simplest implementation
Georges Racinet <georges.racinet@octobus.net>
parents:
44227
diff
changeset
|
707 } |
e52401a95b94
rust-nodemap: NodeMap trait with simplest implementation
Georges Racinet <georges.racinet@octobus.net>
parents:
44227
diff
changeset
|
708 } |
e52401a95b94
rust-nodemap: NodeMap trait with simplest implementation
Georges Racinet <georges.racinet@octobus.net>
parents:
44227
diff
changeset
|
709 |
44390
d2da8667125b
rust-nodemap: insert method
Georges Racinet <georges.racinet@octobus.net>
parents:
44261
diff
changeset
|
710 impl Default for NodeTree { |
d2da8667125b
rust-nodemap: insert method
Georges Racinet <georges.racinet@octobus.net>
parents:
44261
diff
changeset
|
711 /// Create a fully mutable empty NodeTree |
d2da8667125b
rust-nodemap: insert method
Georges Racinet <georges.racinet@octobus.net>
parents:
44261
diff
changeset
|
712 fn default() -> Self { |
d2da8667125b
rust-nodemap: insert method
Georges Racinet <georges.racinet@octobus.net>
parents:
44261
diff
changeset
|
713 NodeTree::new(Box::new(Vec::new())) |
d2da8667125b
rust-nodemap: insert method
Georges Racinet <georges.racinet@octobus.net>
parents:
44261
diff
changeset
|
714 } |
d2da8667125b
rust-nodemap: insert method
Georges Racinet <georges.racinet@octobus.net>
parents:
44261
diff
changeset
|
715 } |
d2da8667125b
rust-nodemap: insert method
Georges Racinet <georges.racinet@octobus.net>
parents:
44261
diff
changeset
|
716 |
44258
e52401a95b94
rust-nodemap: NodeMap trait with simplest implementation
Georges Racinet <georges.racinet@octobus.net>
parents:
44227
diff
changeset
|
717 impl NodeMap for NodeTree { |
e52401a95b94
rust-nodemap: NodeMap trait with simplest implementation
Georges Racinet <georges.racinet@octobus.net>
parents:
44227
diff
changeset
|
718 fn find_bin<'a>( |
e52401a95b94
rust-nodemap: NodeMap trait with simplest implementation
Georges Racinet <georges.racinet@octobus.net>
parents:
44227
diff
changeset
|
719 &self, |
e52401a95b94
rust-nodemap: NodeMap trait with simplest implementation
Georges Racinet <georges.racinet@octobus.net>
parents:
44227
diff
changeset
|
720 idx: &impl RevlogIndex, |
e52401a95b94
rust-nodemap: NodeMap trait with simplest implementation
Georges Racinet <georges.racinet@octobus.net>
parents:
44227
diff
changeset
|
721 prefix: NodePrefixRef<'a>, |
e52401a95b94
rust-nodemap: NodeMap trait with simplest implementation
Georges Racinet <georges.racinet@octobus.net>
parents:
44227
diff
changeset
|
722 ) -> Result<Option<Revision>, NodeMapError> { |
44418
00d251d32007
rust-nodemap: special case for prefixes of NULL_NODE
Georges Racinet <georges.racinet@octobus.net>
parents:
44416
diff
changeset
|
723 validate_candidate(idx, prefix.clone(), self.lookup(prefix)?) |
44419
5ac1eecc9c64
rust-nodemap: core implementation for shortest
Georges Racinet <georges.racinet@octobus.net>
parents:
44418
diff
changeset
|
724 .map(|(opt, _shortest)| opt) |
5ac1eecc9c64
rust-nodemap: core implementation for shortest
Georges Racinet <georges.racinet@octobus.net>
parents:
44418
diff
changeset
|
725 } |
5ac1eecc9c64
rust-nodemap: core implementation for shortest
Georges Racinet <georges.racinet@octobus.net>
parents:
44418
diff
changeset
|
726 |
5ac1eecc9c64
rust-nodemap: core implementation for shortest
Georges Racinet <georges.racinet@octobus.net>
parents:
44418
diff
changeset
|
727 fn unique_prefix_len_bin<'a>( |
5ac1eecc9c64
rust-nodemap: core implementation for shortest
Georges Racinet <georges.racinet@octobus.net>
parents:
44418
diff
changeset
|
728 &self, |
5ac1eecc9c64
rust-nodemap: core implementation for shortest
Georges Racinet <georges.racinet@octobus.net>
parents:
44418
diff
changeset
|
729 idx: &impl RevlogIndex, |
5ac1eecc9c64
rust-nodemap: core implementation for shortest
Georges Racinet <georges.racinet@octobus.net>
parents:
44418
diff
changeset
|
730 prefix: NodePrefixRef<'a>, |
5ac1eecc9c64
rust-nodemap: core implementation for shortest
Georges Racinet <georges.racinet@octobus.net>
parents:
44418
diff
changeset
|
731 ) -> Result<Option<usize>, NodeMapError> { |
5ac1eecc9c64
rust-nodemap: core implementation for shortest
Georges Racinet <georges.racinet@octobus.net>
parents:
44418
diff
changeset
|
732 validate_candidate(idx, prefix.clone(), self.lookup(prefix)?) |
5ac1eecc9c64
rust-nodemap: core implementation for shortest
Georges Racinet <georges.racinet@octobus.net>
parents:
44418
diff
changeset
|
733 .map(|(opt, shortest)| opt.map(|_rev| shortest)) |
44258
e52401a95b94
rust-nodemap: NodeMap trait with simplest implementation
Georges Racinet <georges.racinet@octobus.net>
parents:
44227
diff
changeset
|
734 } |
e52401a95b94
rust-nodemap: NodeMap trait with simplest implementation
Georges Racinet <georges.racinet@octobus.net>
parents:
44227
diff
changeset
|
735 } |
e52401a95b94
rust-nodemap: NodeMap trait with simplest implementation
Georges Racinet <georges.racinet@octobus.net>
parents:
44227
diff
changeset
|
736 |
44227
63db6657d280
rust-nodemap: building blocks for nodetree structures
Georges Racinet <georges.racinet@octobus.net>
parents:
diff
changeset
|
737 #[cfg(test)] |
63db6657d280
rust-nodemap: building blocks for nodetree structures
Georges Racinet <georges.racinet@octobus.net>
parents:
diff
changeset
|
738 mod tests { |
44258
e52401a95b94
rust-nodemap: NodeMap trait with simplest implementation
Georges Racinet <georges.racinet@octobus.net>
parents:
44227
diff
changeset
|
739 use super::NodeMapError::*; |
44227
63db6657d280
rust-nodemap: building blocks for nodetree structures
Georges Racinet <georges.racinet@octobus.net>
parents:
diff
changeset
|
740 use super::*; |
44258
e52401a95b94
rust-nodemap: NodeMap trait with simplest implementation
Georges Racinet <georges.racinet@octobus.net>
parents:
44227
diff
changeset
|
741 use crate::revlog::node::{hex_pad_right, Node}; |
e52401a95b94
rust-nodemap: NodeMap trait with simplest implementation
Georges Racinet <georges.racinet@octobus.net>
parents:
44227
diff
changeset
|
742 use std::collections::HashMap; |
44227
63db6657d280
rust-nodemap: building blocks for nodetree structures
Georges Racinet <georges.racinet@octobus.net>
parents:
diff
changeset
|
743 |
63db6657d280
rust-nodemap: building blocks for nodetree structures
Georges Racinet <georges.racinet@octobus.net>
parents:
diff
changeset
|
744 /// Creates a `Block` using a syntax close to the `Debug` output |
63db6657d280
rust-nodemap: building blocks for nodetree structures
Georges Racinet <georges.racinet@octobus.net>
parents:
diff
changeset
|
745 macro_rules! block { |
63db6657d280
rust-nodemap: building blocks for nodetree structures
Georges Racinet <georges.racinet@octobus.net>
parents:
diff
changeset
|
746 {$($nybble:tt : $variant:ident($val:tt)),*} => ( |
63db6657d280
rust-nodemap: building blocks for nodetree structures
Georges Racinet <georges.racinet@octobus.net>
parents:
diff
changeset
|
747 { |
63db6657d280
rust-nodemap: building blocks for nodetree structures
Georges Racinet <georges.racinet@octobus.net>
parents:
diff
changeset
|
748 let mut block = Block::new(); |
63db6657d280
rust-nodemap: building blocks for nodetree structures
Georges Racinet <georges.racinet@octobus.net>
parents:
diff
changeset
|
749 $(block.set($nybble, Element::$variant($val)));*; |
63db6657d280
rust-nodemap: building blocks for nodetree structures
Georges Racinet <georges.racinet@octobus.net>
parents:
diff
changeset
|
750 block |
63db6657d280
rust-nodemap: building blocks for nodetree structures
Georges Racinet <georges.racinet@octobus.net>
parents:
diff
changeset
|
751 } |
63db6657d280
rust-nodemap: building blocks for nodetree structures
Georges Racinet <georges.racinet@octobus.net>
parents:
diff
changeset
|
752 ) |
63db6657d280
rust-nodemap: building blocks for nodetree structures
Georges Racinet <georges.racinet@octobus.net>
parents:
diff
changeset
|
753 } |
63db6657d280
rust-nodemap: building blocks for nodetree structures
Georges Racinet <georges.racinet@octobus.net>
parents:
diff
changeset
|
754 |
63db6657d280
rust-nodemap: building blocks for nodetree structures
Georges Racinet <georges.racinet@octobus.net>
parents:
diff
changeset
|
755 #[test] |
63db6657d280
rust-nodemap: building blocks for nodetree structures
Georges Racinet <georges.racinet@octobus.net>
parents:
diff
changeset
|
756 fn test_block_debug() { |
63db6657d280
rust-nodemap: building blocks for nodetree structures
Georges Racinet <georges.racinet@octobus.net>
parents:
diff
changeset
|
757 let mut block = Block::new(); |
63db6657d280
rust-nodemap: building blocks for nodetree structures
Georges Racinet <georges.racinet@octobus.net>
parents:
diff
changeset
|
758 block.set(1, Element::Rev(3)); |
63db6657d280
rust-nodemap: building blocks for nodetree structures
Georges Racinet <georges.racinet@octobus.net>
parents:
diff
changeset
|
759 block.set(10, Element::Block(0)); |
63db6657d280
rust-nodemap: building blocks for nodetree structures
Georges Racinet <georges.racinet@octobus.net>
parents:
diff
changeset
|
760 assert_eq!(format!("{:?}", block), "{1: Rev(3), 10: Block(0)}"); |
63db6657d280
rust-nodemap: building blocks for nodetree structures
Georges Racinet <georges.racinet@octobus.net>
parents:
diff
changeset
|
761 } |
63db6657d280
rust-nodemap: building blocks for nodetree structures
Georges Racinet <georges.racinet@octobus.net>
parents:
diff
changeset
|
762 |
63db6657d280
rust-nodemap: building blocks for nodetree structures
Georges Racinet <georges.racinet@octobus.net>
parents:
diff
changeset
|
763 #[test] |
63db6657d280
rust-nodemap: building blocks for nodetree structures
Georges Racinet <georges.racinet@octobus.net>
parents:
diff
changeset
|
764 fn test_block_macro() { |
63db6657d280
rust-nodemap: building blocks for nodetree structures
Georges Racinet <georges.racinet@octobus.net>
parents:
diff
changeset
|
765 let block = block! {5: Block(2)}; |
63db6657d280
rust-nodemap: building blocks for nodetree structures
Georges Racinet <georges.racinet@octobus.net>
parents:
diff
changeset
|
766 assert_eq!(format!("{:?}", block), "{5: Block(2)}"); |
63db6657d280
rust-nodemap: building blocks for nodetree structures
Georges Racinet <georges.racinet@octobus.net>
parents:
diff
changeset
|
767 |
63db6657d280
rust-nodemap: building blocks for nodetree structures
Georges Racinet <georges.racinet@octobus.net>
parents:
diff
changeset
|
768 let block = block! {13: Rev(15), 5: Block(2)}; |
63db6657d280
rust-nodemap: building blocks for nodetree structures
Georges Racinet <georges.racinet@octobus.net>
parents:
diff
changeset
|
769 assert_eq!(format!("{:?}", block), "{5: Block(2), 13: Rev(15)}"); |
63db6657d280
rust-nodemap: building blocks for nodetree structures
Georges Racinet <georges.racinet@octobus.net>
parents:
diff
changeset
|
770 } |
63db6657d280
rust-nodemap: building blocks for nodetree structures
Georges Racinet <georges.racinet@octobus.net>
parents:
diff
changeset
|
771 |
63db6657d280
rust-nodemap: building blocks for nodetree structures
Georges Racinet <georges.racinet@octobus.net>
parents:
diff
changeset
|
772 #[test] |
63db6657d280
rust-nodemap: building blocks for nodetree structures
Georges Racinet <georges.racinet@octobus.net>
parents:
diff
changeset
|
773 fn test_raw_block() { |
44416
a98ba6983a63
rust-nodemap: input/output primitives
Georges Racinet <georges.racinet@octobus.net>
parents:
44390
diff
changeset
|
774 let mut raw = [255u8; 64]; |
a98ba6983a63
rust-nodemap: input/output primitives
Georges Racinet <georges.racinet@octobus.net>
parents:
44390
diff
changeset
|
775 |
a98ba6983a63
rust-nodemap: input/output primitives
Georges Racinet <georges.racinet@octobus.net>
parents:
44390
diff
changeset
|
776 let mut counter = 0; |
a98ba6983a63
rust-nodemap: input/output primitives
Georges Racinet <georges.racinet@octobus.net>
parents:
44390
diff
changeset
|
777 for val in [0, 15, -2, -1, -3].iter() { |
a98ba6983a63
rust-nodemap: input/output primitives
Georges Racinet <georges.racinet@octobus.net>
parents:
44390
diff
changeset
|
778 for byte in RawElement::to_be_bytes(*val).iter() { |
a98ba6983a63
rust-nodemap: input/output primitives
Georges Racinet <georges.racinet@octobus.net>
parents:
44390
diff
changeset
|
779 raw[counter] = *byte; |
a98ba6983a63
rust-nodemap: input/output primitives
Georges Racinet <georges.racinet@octobus.net>
parents:
44390
diff
changeset
|
780 counter += 1; |
a98ba6983a63
rust-nodemap: input/output primitives
Georges Racinet <georges.racinet@octobus.net>
parents:
44390
diff
changeset
|
781 } |
a98ba6983a63
rust-nodemap: input/output primitives
Georges Racinet <georges.racinet@octobus.net>
parents:
44390
diff
changeset
|
782 } |
44227
63db6657d280
rust-nodemap: building blocks for nodetree structures
Georges Racinet <georges.racinet@octobus.net>
parents:
diff
changeset
|
783 let block = Block(raw); |
63db6657d280
rust-nodemap: building blocks for nodetree structures
Georges Racinet <georges.racinet@octobus.net>
parents:
diff
changeset
|
784 assert_eq!(block.get(0), Element::Block(0)); |
63db6657d280
rust-nodemap: building blocks for nodetree structures
Georges Racinet <georges.racinet@octobus.net>
parents:
diff
changeset
|
785 assert_eq!(block.get(1), Element::Block(15)); |
63db6657d280
rust-nodemap: building blocks for nodetree structures
Georges Racinet <georges.racinet@octobus.net>
parents:
diff
changeset
|
786 assert_eq!(block.get(3), Element::None); |
63db6657d280
rust-nodemap: building blocks for nodetree structures
Georges Racinet <georges.racinet@octobus.net>
parents:
diff
changeset
|
787 assert_eq!(block.get(2), Element::Rev(0)); |
63db6657d280
rust-nodemap: building blocks for nodetree structures
Georges Racinet <georges.racinet@octobus.net>
parents:
diff
changeset
|
788 assert_eq!(block.get(4), Element::Rev(1)); |
63db6657d280
rust-nodemap: building blocks for nodetree structures
Georges Racinet <georges.racinet@octobus.net>
parents:
diff
changeset
|
789 } |
44258
e52401a95b94
rust-nodemap: NodeMap trait with simplest implementation
Georges Racinet <georges.racinet@octobus.net>
parents:
44227
diff
changeset
|
790 |
e52401a95b94
rust-nodemap: NodeMap trait with simplest implementation
Georges Racinet <georges.racinet@octobus.net>
parents:
44227
diff
changeset
|
791 type TestIndex = HashMap<Revision, Node>; |
e52401a95b94
rust-nodemap: NodeMap trait with simplest implementation
Georges Racinet <georges.racinet@octobus.net>
parents:
44227
diff
changeset
|
792 |
e52401a95b94
rust-nodemap: NodeMap trait with simplest implementation
Georges Racinet <georges.racinet@octobus.net>
parents:
44227
diff
changeset
|
793 impl RevlogIndex for TestIndex { |
e52401a95b94
rust-nodemap: NodeMap trait with simplest implementation
Georges Racinet <georges.racinet@octobus.net>
parents:
44227
diff
changeset
|
794 fn node(&self, rev: Revision) -> Option<&Node> { |
e52401a95b94
rust-nodemap: NodeMap trait with simplest implementation
Georges Racinet <georges.racinet@octobus.net>
parents:
44227
diff
changeset
|
795 self.get(&rev) |
e52401a95b94
rust-nodemap: NodeMap trait with simplest implementation
Georges Racinet <georges.racinet@octobus.net>
parents:
44227
diff
changeset
|
796 } |
e52401a95b94
rust-nodemap: NodeMap trait with simplest implementation
Georges Racinet <georges.racinet@octobus.net>
parents:
44227
diff
changeset
|
797 |
e52401a95b94
rust-nodemap: NodeMap trait with simplest implementation
Georges Racinet <georges.racinet@octobus.net>
parents:
44227
diff
changeset
|
798 fn len(&self) -> usize { |
e52401a95b94
rust-nodemap: NodeMap trait with simplest implementation
Georges Racinet <georges.racinet@octobus.net>
parents:
44227
diff
changeset
|
799 self.len() |
e52401a95b94
rust-nodemap: NodeMap trait with simplest implementation
Georges Racinet <georges.racinet@octobus.net>
parents:
44227
diff
changeset
|
800 } |
e52401a95b94
rust-nodemap: NodeMap trait with simplest implementation
Georges Racinet <georges.racinet@octobus.net>
parents:
44227
diff
changeset
|
801 } |
e52401a95b94
rust-nodemap: NodeMap trait with simplest implementation
Georges Racinet <georges.racinet@octobus.net>
parents:
44227
diff
changeset
|
802 |
44390
d2da8667125b
rust-nodemap: insert method
Georges Racinet <georges.racinet@octobus.net>
parents:
44261
diff
changeset
|
803 /// Pad hexadecimal Node prefix with zeros on the right |
44258
e52401a95b94
rust-nodemap: NodeMap trait with simplest implementation
Georges Racinet <georges.racinet@octobus.net>
parents:
44227
diff
changeset
|
804 /// |
e52401a95b94
rust-nodemap: NodeMap trait with simplest implementation
Georges Racinet <georges.racinet@octobus.net>
parents:
44227
diff
changeset
|
805 /// This avoids having to repeatedly write very long hexadecimal |
e52401a95b94
rust-nodemap: NodeMap trait with simplest implementation
Georges Racinet <georges.racinet@octobus.net>
parents:
44227
diff
changeset
|
806 /// strings for test data, and brings actual hash size independency. |
44390
d2da8667125b
rust-nodemap: insert method
Georges Racinet <georges.racinet@octobus.net>
parents:
44261
diff
changeset
|
807 #[cfg(test)] |
d2da8667125b
rust-nodemap: insert method
Georges Racinet <georges.racinet@octobus.net>
parents:
44261
diff
changeset
|
808 fn pad_node(hex: &str) -> Node { |
d2da8667125b
rust-nodemap: insert method
Georges Racinet <georges.racinet@octobus.net>
parents:
44261
diff
changeset
|
809 Node::from_hex(&hex_pad_right(hex)).unwrap() |
d2da8667125b
rust-nodemap: insert method
Georges Racinet <georges.racinet@octobus.net>
parents:
44261
diff
changeset
|
810 } |
d2da8667125b
rust-nodemap: insert method
Georges Racinet <georges.racinet@octobus.net>
parents:
44261
diff
changeset
|
811 |
d2da8667125b
rust-nodemap: insert method
Georges Racinet <georges.racinet@octobus.net>
parents:
44261
diff
changeset
|
812 /// Pad hexadecimal Node prefix with zeros on the right, then insert |
44258
e52401a95b94
rust-nodemap: NodeMap trait with simplest implementation
Georges Racinet <georges.racinet@octobus.net>
parents:
44227
diff
changeset
|
813 fn pad_insert(idx: &mut TestIndex, rev: Revision, hex: &str) { |
44390
d2da8667125b
rust-nodemap: insert method
Georges Racinet <georges.racinet@octobus.net>
parents:
44261
diff
changeset
|
814 idx.insert(rev, pad_node(hex)); |
44258
e52401a95b94
rust-nodemap: NodeMap trait with simplest implementation
Georges Racinet <georges.racinet@octobus.net>
parents:
44227
diff
changeset
|
815 } |
e52401a95b94
rust-nodemap: NodeMap trait with simplest implementation
Georges Racinet <georges.racinet@octobus.net>
parents:
44227
diff
changeset
|
816 |
e52401a95b94
rust-nodemap: NodeMap trait with simplest implementation
Georges Racinet <georges.racinet@octobus.net>
parents:
44227
diff
changeset
|
817 fn sample_nodetree() -> NodeTree { |
e52401a95b94
rust-nodemap: NodeMap trait with simplest implementation
Georges Racinet <georges.racinet@octobus.net>
parents:
44227
diff
changeset
|
818 NodeTree::from(vec![ |
e52401a95b94
rust-nodemap: NodeMap trait with simplest implementation
Georges Racinet <georges.racinet@octobus.net>
parents:
44227
diff
changeset
|
819 block![0: Rev(9)], |
e52401a95b94
rust-nodemap: NodeMap trait with simplest implementation
Georges Racinet <georges.racinet@octobus.net>
parents:
44227
diff
changeset
|
820 block![0: Rev(0), 1: Rev(9)], |
e52401a95b94
rust-nodemap: NodeMap trait with simplest implementation
Georges Racinet <georges.racinet@octobus.net>
parents:
44227
diff
changeset
|
821 block![0: Block(1), 1:Rev(1)], |
e52401a95b94
rust-nodemap: NodeMap trait with simplest implementation
Georges Racinet <georges.racinet@octobus.net>
parents:
44227
diff
changeset
|
822 ]) |
e52401a95b94
rust-nodemap: NodeMap trait with simplest implementation
Georges Racinet <georges.racinet@octobus.net>
parents:
44227
diff
changeset
|
823 } |
e52401a95b94
rust-nodemap: NodeMap trait with simplest implementation
Georges Racinet <georges.racinet@octobus.net>
parents:
44227
diff
changeset
|
824 |
e52401a95b94
rust-nodemap: NodeMap trait with simplest implementation
Georges Racinet <georges.racinet@octobus.net>
parents:
44227
diff
changeset
|
825 #[test] |
e52401a95b94
rust-nodemap: NodeMap trait with simplest implementation
Georges Racinet <georges.racinet@octobus.net>
parents:
44227
diff
changeset
|
826 fn test_nt_debug() { |
e52401a95b94
rust-nodemap: NodeMap trait with simplest implementation
Georges Racinet <georges.racinet@octobus.net>
parents:
44227
diff
changeset
|
827 let nt = sample_nodetree(); |
e52401a95b94
rust-nodemap: NodeMap trait with simplest implementation
Georges Racinet <georges.racinet@octobus.net>
parents:
44227
diff
changeset
|
828 assert_eq!( |
e52401a95b94
rust-nodemap: NodeMap trait with simplest implementation
Georges Racinet <georges.racinet@octobus.net>
parents:
44227
diff
changeset
|
829 format!("{:?}", nt), |
e52401a95b94
rust-nodemap: NodeMap trait with simplest implementation
Georges Racinet <georges.racinet@octobus.net>
parents:
44227
diff
changeset
|
830 "readonly: \ |
44260
a19331456d48
rust-nodemap: mutable NodeTree data structure
Georges Racinet <georges.racinet@octobus.net>
parents:
44259
diff
changeset
|
831 [{0: Rev(9)}, {0: Rev(0), 1: Rev(9)}, {0: Block(1), 1: Rev(1)}], \ |
a19331456d48
rust-nodemap: mutable NodeTree data structure
Georges Racinet <georges.racinet@octobus.net>
parents:
44259
diff
changeset
|
832 growable: [], \ |
a19331456d48
rust-nodemap: mutable NodeTree data structure
Georges Racinet <georges.racinet@octobus.net>
parents:
44259
diff
changeset
|
833 root: {0: Block(1), 1: Rev(1)}", |
44258
e52401a95b94
rust-nodemap: NodeMap trait with simplest implementation
Georges Racinet <georges.racinet@octobus.net>
parents:
44227
diff
changeset
|
834 ); |
e52401a95b94
rust-nodemap: NodeMap trait with simplest implementation
Georges Racinet <georges.racinet@octobus.net>
parents:
44227
diff
changeset
|
835 } |
e52401a95b94
rust-nodemap: NodeMap trait with simplest implementation
Georges Racinet <georges.racinet@octobus.net>
parents:
44227
diff
changeset
|
836 |
e52401a95b94
rust-nodemap: NodeMap trait with simplest implementation
Georges Racinet <georges.racinet@octobus.net>
parents:
44227
diff
changeset
|
837 #[test] |
e52401a95b94
rust-nodemap: NodeMap trait with simplest implementation
Georges Racinet <georges.racinet@octobus.net>
parents:
44227
diff
changeset
|
838 fn test_immutable_find_simplest() -> Result<(), NodeMapError> { |
e52401a95b94
rust-nodemap: NodeMap trait with simplest implementation
Georges Racinet <georges.racinet@octobus.net>
parents:
44227
diff
changeset
|
839 let mut idx: TestIndex = HashMap::new(); |
e52401a95b94
rust-nodemap: NodeMap trait with simplest implementation
Georges Racinet <georges.racinet@octobus.net>
parents:
44227
diff
changeset
|
840 pad_insert(&mut idx, 1, "1234deadcafe"); |
e52401a95b94
rust-nodemap: NodeMap trait with simplest implementation
Georges Racinet <georges.racinet@octobus.net>
parents:
44227
diff
changeset
|
841 |
44260
a19331456d48
rust-nodemap: mutable NodeTree data structure
Georges Racinet <georges.racinet@octobus.net>
parents:
44259
diff
changeset
|
842 let nt = NodeTree::from(vec![block! {1: Rev(1)}]); |
44258
e52401a95b94
rust-nodemap: NodeMap trait with simplest implementation
Georges Racinet <georges.racinet@octobus.net>
parents:
44227
diff
changeset
|
843 assert_eq!(nt.find_hex(&idx, "1")?, Some(1)); |
e52401a95b94
rust-nodemap: NodeMap trait with simplest implementation
Georges Racinet <georges.racinet@octobus.net>
parents:
44227
diff
changeset
|
844 assert_eq!(nt.find_hex(&idx, "12")?, Some(1)); |
e52401a95b94
rust-nodemap: NodeMap trait with simplest implementation
Georges Racinet <georges.racinet@octobus.net>
parents:
44227
diff
changeset
|
845 assert_eq!(nt.find_hex(&idx, "1234de")?, Some(1)); |
e52401a95b94
rust-nodemap: NodeMap trait with simplest implementation
Georges Racinet <georges.racinet@octobus.net>
parents:
44227
diff
changeset
|
846 assert_eq!(nt.find_hex(&idx, "1a")?, None); |
e52401a95b94
rust-nodemap: NodeMap trait with simplest implementation
Georges Racinet <georges.racinet@octobus.net>
parents:
44227
diff
changeset
|
847 assert_eq!(nt.find_hex(&idx, "ab")?, None); |
e52401a95b94
rust-nodemap: NodeMap trait with simplest implementation
Georges Racinet <georges.racinet@octobus.net>
parents:
44227
diff
changeset
|
848 |
e52401a95b94
rust-nodemap: NodeMap trait with simplest implementation
Georges Racinet <georges.racinet@octobus.net>
parents:
44227
diff
changeset
|
849 // and with full binary Nodes |
e52401a95b94
rust-nodemap: NodeMap trait with simplest implementation
Georges Racinet <georges.racinet@octobus.net>
parents:
44227
diff
changeset
|
850 assert_eq!(nt.find_node(&idx, idx.get(&1).unwrap())?, Some(1)); |
e52401a95b94
rust-nodemap: NodeMap trait with simplest implementation
Georges Racinet <georges.racinet@octobus.net>
parents:
44227
diff
changeset
|
851 let unknown = Node::from_hex(&hex_pad_right("3d")).unwrap(); |
e52401a95b94
rust-nodemap: NodeMap trait with simplest implementation
Georges Racinet <georges.racinet@octobus.net>
parents:
44227
diff
changeset
|
852 assert_eq!(nt.find_node(&idx, &unknown)?, None); |
e52401a95b94
rust-nodemap: NodeMap trait with simplest implementation
Georges Racinet <georges.racinet@octobus.net>
parents:
44227
diff
changeset
|
853 Ok(()) |
e52401a95b94
rust-nodemap: NodeMap trait with simplest implementation
Georges Racinet <georges.racinet@octobus.net>
parents:
44227
diff
changeset
|
854 } |
e52401a95b94
rust-nodemap: NodeMap trait with simplest implementation
Georges Racinet <georges.racinet@octobus.net>
parents:
44227
diff
changeset
|
855 |
e52401a95b94
rust-nodemap: NodeMap trait with simplest implementation
Georges Racinet <georges.racinet@octobus.net>
parents:
44227
diff
changeset
|
856 #[test] |
e52401a95b94
rust-nodemap: NodeMap trait with simplest implementation
Georges Racinet <georges.racinet@octobus.net>
parents:
44227
diff
changeset
|
857 fn test_immutable_find_one_jump() { |
e52401a95b94
rust-nodemap: NodeMap trait with simplest implementation
Georges Racinet <georges.racinet@octobus.net>
parents:
44227
diff
changeset
|
858 let mut idx = TestIndex::new(); |
e52401a95b94
rust-nodemap: NodeMap trait with simplest implementation
Georges Racinet <georges.racinet@octobus.net>
parents:
44227
diff
changeset
|
859 pad_insert(&mut idx, 9, "012"); |
e52401a95b94
rust-nodemap: NodeMap trait with simplest implementation
Georges Racinet <georges.racinet@octobus.net>
parents:
44227
diff
changeset
|
860 pad_insert(&mut idx, 0, "00a"); |
e52401a95b94
rust-nodemap: NodeMap trait with simplest implementation
Georges Racinet <georges.racinet@octobus.net>
parents:
44227
diff
changeset
|
861 |
e52401a95b94
rust-nodemap: NodeMap trait with simplest implementation
Georges Racinet <georges.racinet@octobus.net>
parents:
44227
diff
changeset
|
862 let nt = sample_nodetree(); |
e52401a95b94
rust-nodemap: NodeMap trait with simplest implementation
Georges Racinet <georges.racinet@octobus.net>
parents:
44227
diff
changeset
|
863 |
e52401a95b94
rust-nodemap: NodeMap trait with simplest implementation
Georges Racinet <georges.racinet@octobus.net>
parents:
44227
diff
changeset
|
864 assert_eq!(nt.find_hex(&idx, "0"), Err(MultipleResults)); |
e52401a95b94
rust-nodemap: NodeMap trait with simplest implementation
Georges Racinet <georges.racinet@octobus.net>
parents:
44227
diff
changeset
|
865 assert_eq!(nt.find_hex(&idx, "01"), Ok(Some(9))); |
44418
00d251d32007
rust-nodemap: special case for prefixes of NULL_NODE
Georges Racinet <georges.racinet@octobus.net>
parents:
44416
diff
changeset
|
866 assert_eq!(nt.find_hex(&idx, "00"), Err(MultipleResults)); |
44258
e52401a95b94
rust-nodemap: NodeMap trait with simplest implementation
Georges Racinet <georges.racinet@octobus.net>
parents:
44227
diff
changeset
|
867 assert_eq!(nt.find_hex(&idx, "00a"), Ok(Some(0))); |
44419
5ac1eecc9c64
rust-nodemap: core implementation for shortest
Georges Racinet <georges.racinet@octobus.net>
parents:
44418
diff
changeset
|
868 assert_eq!(nt.unique_prefix_len_hex(&idx, "00a"), Ok(Some(3))); |
44418
00d251d32007
rust-nodemap: special case for prefixes of NULL_NODE
Georges Racinet <georges.racinet@octobus.net>
parents:
44416
diff
changeset
|
869 assert_eq!(nt.find_hex(&idx, "000"), Ok(Some(NULL_REVISION))); |
44258
e52401a95b94
rust-nodemap: NodeMap trait with simplest implementation
Georges Racinet <georges.racinet@octobus.net>
parents:
44227
diff
changeset
|
870 } |
44260
a19331456d48
rust-nodemap: mutable NodeTree data structure
Georges Racinet <georges.racinet@octobus.net>
parents:
44259
diff
changeset
|
871 |
a19331456d48
rust-nodemap: mutable NodeTree data structure
Georges Racinet <georges.racinet@octobus.net>
parents:
44259
diff
changeset
|
872 #[test] |
a19331456d48
rust-nodemap: mutable NodeTree data structure
Georges Racinet <georges.racinet@octobus.net>
parents:
44259
diff
changeset
|
873 fn test_mutated_find() -> Result<(), NodeMapError> { |
a19331456d48
rust-nodemap: mutable NodeTree data structure
Georges Racinet <georges.racinet@octobus.net>
parents:
44259
diff
changeset
|
874 let mut idx = TestIndex::new(); |
a19331456d48
rust-nodemap: mutable NodeTree data structure
Georges Racinet <georges.racinet@octobus.net>
parents:
44259
diff
changeset
|
875 pad_insert(&mut idx, 9, "012"); |
a19331456d48
rust-nodemap: mutable NodeTree data structure
Georges Racinet <georges.racinet@octobus.net>
parents:
44259
diff
changeset
|
876 pad_insert(&mut idx, 0, "00a"); |
a19331456d48
rust-nodemap: mutable NodeTree data structure
Georges Racinet <georges.racinet@octobus.net>
parents:
44259
diff
changeset
|
877 pad_insert(&mut idx, 2, "cafe"); |
a19331456d48
rust-nodemap: mutable NodeTree data structure
Georges Racinet <georges.racinet@octobus.net>
parents:
44259
diff
changeset
|
878 pad_insert(&mut idx, 3, "15"); |
a19331456d48
rust-nodemap: mutable NodeTree data structure
Georges Racinet <georges.racinet@octobus.net>
parents:
44259
diff
changeset
|
879 pad_insert(&mut idx, 1, "10"); |
a19331456d48
rust-nodemap: mutable NodeTree data structure
Georges Racinet <georges.racinet@octobus.net>
parents:
44259
diff
changeset
|
880 |
a19331456d48
rust-nodemap: mutable NodeTree data structure
Georges Racinet <georges.racinet@octobus.net>
parents:
44259
diff
changeset
|
881 let nt = NodeTree { |
a19331456d48
rust-nodemap: mutable NodeTree data structure
Georges Racinet <georges.racinet@octobus.net>
parents:
44259
diff
changeset
|
882 readonly: sample_nodetree().readonly, |
a19331456d48
rust-nodemap: mutable NodeTree data structure
Georges Racinet <georges.racinet@octobus.net>
parents:
44259
diff
changeset
|
883 growable: vec![block![0: Rev(1), 5: Rev(3)]], |
a19331456d48
rust-nodemap: mutable NodeTree data structure
Georges Racinet <georges.racinet@octobus.net>
parents:
44259
diff
changeset
|
884 root: block![0: Block(1), 1:Block(3), 12: Rev(2)], |
44420
6329ce04c69f
rust-nodemap: accounting for dead blocks
Georges Racinet <georges.racinet@octobus.net>
parents:
44419
diff
changeset
|
885 masked_inner_blocks: 1, |
44260
a19331456d48
rust-nodemap: mutable NodeTree data structure
Georges Racinet <georges.racinet@octobus.net>
parents:
44259
diff
changeset
|
886 }; |
a19331456d48
rust-nodemap: mutable NodeTree data structure
Georges Racinet <georges.racinet@octobus.net>
parents:
44259
diff
changeset
|
887 assert_eq!(nt.find_hex(&idx, "10")?, Some(1)); |
a19331456d48
rust-nodemap: mutable NodeTree data structure
Georges Racinet <georges.racinet@octobus.net>
parents:
44259
diff
changeset
|
888 assert_eq!(nt.find_hex(&idx, "c")?, Some(2)); |
44419
5ac1eecc9c64
rust-nodemap: core implementation for shortest
Georges Racinet <georges.racinet@octobus.net>
parents:
44418
diff
changeset
|
889 assert_eq!(nt.unique_prefix_len_hex(&idx, "c")?, Some(1)); |
44418
00d251d32007
rust-nodemap: special case for prefixes of NULL_NODE
Georges Racinet <georges.racinet@octobus.net>
parents:
44416
diff
changeset
|
890 assert_eq!(nt.find_hex(&idx, "00"), Err(MultipleResults)); |
00d251d32007
rust-nodemap: special case for prefixes of NULL_NODE
Georges Racinet <georges.racinet@octobus.net>
parents:
44416
diff
changeset
|
891 assert_eq!(nt.find_hex(&idx, "000")?, Some(NULL_REVISION)); |
44419
5ac1eecc9c64
rust-nodemap: core implementation for shortest
Georges Racinet <georges.racinet@octobus.net>
parents:
44418
diff
changeset
|
892 assert_eq!(nt.unique_prefix_len_hex(&idx, "000")?, Some(3)); |
44260
a19331456d48
rust-nodemap: mutable NodeTree data structure
Georges Racinet <georges.racinet@octobus.net>
parents:
44259
diff
changeset
|
893 assert_eq!(nt.find_hex(&idx, "01")?, Some(9)); |
44420
6329ce04c69f
rust-nodemap: accounting for dead blocks
Georges Racinet <georges.racinet@octobus.net>
parents:
44419
diff
changeset
|
894 assert_eq!(nt.masked_readonly_blocks(), 2); |
44260
a19331456d48
rust-nodemap: mutable NodeTree data structure
Georges Racinet <georges.racinet@octobus.net>
parents:
44259
diff
changeset
|
895 Ok(()) |
a19331456d48
rust-nodemap: mutable NodeTree data structure
Georges Racinet <georges.racinet@octobus.net>
parents:
44259
diff
changeset
|
896 } |
44390
d2da8667125b
rust-nodemap: insert method
Georges Racinet <georges.racinet@octobus.net>
parents:
44261
diff
changeset
|
897 |
d2da8667125b
rust-nodemap: insert method
Georges Racinet <georges.racinet@octobus.net>
parents:
44261
diff
changeset
|
898 struct TestNtIndex { |
d2da8667125b
rust-nodemap: insert method
Georges Racinet <georges.racinet@octobus.net>
parents:
44261
diff
changeset
|
899 index: TestIndex, |
d2da8667125b
rust-nodemap: insert method
Georges Racinet <georges.racinet@octobus.net>
parents:
44261
diff
changeset
|
900 nt: NodeTree, |
d2da8667125b
rust-nodemap: insert method
Georges Racinet <georges.racinet@octobus.net>
parents:
44261
diff
changeset
|
901 } |
d2da8667125b
rust-nodemap: insert method
Georges Racinet <georges.racinet@octobus.net>
parents:
44261
diff
changeset
|
902 |
d2da8667125b
rust-nodemap: insert method
Georges Racinet <georges.racinet@octobus.net>
parents:
44261
diff
changeset
|
903 impl TestNtIndex { |
d2da8667125b
rust-nodemap: insert method
Georges Racinet <georges.racinet@octobus.net>
parents:
44261
diff
changeset
|
904 fn new() -> Self { |
d2da8667125b
rust-nodemap: insert method
Georges Racinet <georges.racinet@octobus.net>
parents:
44261
diff
changeset
|
905 TestNtIndex { |
d2da8667125b
rust-nodemap: insert method
Georges Racinet <georges.racinet@octobus.net>
parents:
44261
diff
changeset
|
906 index: HashMap::new(), |
d2da8667125b
rust-nodemap: insert method
Georges Racinet <georges.racinet@octobus.net>
parents:
44261
diff
changeset
|
907 nt: NodeTree::default(), |
d2da8667125b
rust-nodemap: insert method
Georges Racinet <georges.racinet@octobus.net>
parents:
44261
diff
changeset
|
908 } |
d2da8667125b
rust-nodemap: insert method
Georges Racinet <georges.racinet@octobus.net>
parents:
44261
diff
changeset
|
909 } |
d2da8667125b
rust-nodemap: insert method
Georges Racinet <georges.racinet@octobus.net>
parents:
44261
diff
changeset
|
910 |
d2da8667125b
rust-nodemap: insert method
Georges Racinet <georges.racinet@octobus.net>
parents:
44261
diff
changeset
|
911 fn insert( |
d2da8667125b
rust-nodemap: insert method
Georges Racinet <georges.racinet@octobus.net>
parents:
44261
diff
changeset
|
912 &mut self, |
d2da8667125b
rust-nodemap: insert method
Georges Racinet <georges.racinet@octobus.net>
parents:
44261
diff
changeset
|
913 rev: Revision, |
d2da8667125b
rust-nodemap: insert method
Georges Racinet <georges.racinet@octobus.net>
parents:
44261
diff
changeset
|
914 hex: &str, |
d2da8667125b
rust-nodemap: insert method
Georges Racinet <georges.racinet@octobus.net>
parents:
44261
diff
changeset
|
915 ) -> Result<(), NodeMapError> { |
d2da8667125b
rust-nodemap: insert method
Georges Racinet <georges.racinet@octobus.net>
parents:
44261
diff
changeset
|
916 let node = pad_node(hex); |
d2da8667125b
rust-nodemap: insert method
Georges Racinet <georges.racinet@octobus.net>
parents:
44261
diff
changeset
|
917 self.index.insert(rev, node.clone()); |
d2da8667125b
rust-nodemap: insert method
Georges Racinet <georges.racinet@octobus.net>
parents:
44261
diff
changeset
|
918 self.nt.insert(&self.index, &node, rev)?; |
d2da8667125b
rust-nodemap: insert method
Georges Racinet <georges.racinet@octobus.net>
parents:
44261
diff
changeset
|
919 Ok(()) |
d2da8667125b
rust-nodemap: insert method
Georges Racinet <georges.racinet@octobus.net>
parents:
44261
diff
changeset
|
920 } |
d2da8667125b
rust-nodemap: insert method
Georges Racinet <georges.racinet@octobus.net>
parents:
44261
diff
changeset
|
921 |
d2da8667125b
rust-nodemap: insert method
Georges Racinet <georges.racinet@octobus.net>
parents:
44261
diff
changeset
|
922 fn find_hex( |
d2da8667125b
rust-nodemap: insert method
Georges Racinet <georges.racinet@octobus.net>
parents:
44261
diff
changeset
|
923 &self, |
d2da8667125b
rust-nodemap: insert method
Georges Racinet <georges.racinet@octobus.net>
parents:
44261
diff
changeset
|
924 prefix: &str, |
d2da8667125b
rust-nodemap: insert method
Georges Racinet <georges.racinet@octobus.net>
parents:
44261
diff
changeset
|
925 ) -> Result<Option<Revision>, NodeMapError> { |
d2da8667125b
rust-nodemap: insert method
Georges Racinet <georges.racinet@octobus.net>
parents:
44261
diff
changeset
|
926 self.nt.find_hex(&self.index, prefix) |
d2da8667125b
rust-nodemap: insert method
Georges Racinet <georges.racinet@octobus.net>
parents:
44261
diff
changeset
|
927 } |
d2da8667125b
rust-nodemap: insert method
Georges Racinet <georges.racinet@octobus.net>
parents:
44261
diff
changeset
|
928 |
44419
5ac1eecc9c64
rust-nodemap: core implementation for shortest
Georges Racinet <georges.racinet@octobus.net>
parents:
44418
diff
changeset
|
929 fn unique_prefix_len_hex( |
5ac1eecc9c64
rust-nodemap: core implementation for shortest
Georges Racinet <georges.racinet@octobus.net>
parents:
44418
diff
changeset
|
930 &self, |
5ac1eecc9c64
rust-nodemap: core implementation for shortest
Georges Racinet <georges.racinet@octobus.net>
parents:
44418
diff
changeset
|
931 prefix: &str, |
5ac1eecc9c64
rust-nodemap: core implementation for shortest
Georges Racinet <georges.racinet@octobus.net>
parents:
44418
diff
changeset
|
932 ) -> Result<Option<usize>, NodeMapError> { |
5ac1eecc9c64
rust-nodemap: core implementation for shortest
Georges Racinet <georges.racinet@octobus.net>
parents:
44418
diff
changeset
|
933 self.nt.unique_prefix_len_hex(&self.index, prefix) |
5ac1eecc9c64
rust-nodemap: core implementation for shortest
Georges Racinet <georges.racinet@octobus.net>
parents:
44418
diff
changeset
|
934 } |
5ac1eecc9c64
rust-nodemap: core implementation for shortest
Georges Racinet <georges.racinet@octobus.net>
parents:
44418
diff
changeset
|
935 |
44390
d2da8667125b
rust-nodemap: insert method
Georges Racinet <georges.racinet@octobus.net>
parents:
44261
diff
changeset
|
936 /// Drain `added` and restart a new one |
d2da8667125b
rust-nodemap: insert method
Georges Racinet <georges.racinet@octobus.net>
parents:
44261
diff
changeset
|
937 fn commit(self) -> Self { |
d2da8667125b
rust-nodemap: insert method
Georges Racinet <georges.racinet@octobus.net>
parents:
44261
diff
changeset
|
938 let mut as_vec: Vec<Block> = |
d2da8667125b
rust-nodemap: insert method
Georges Racinet <georges.racinet@octobus.net>
parents:
44261
diff
changeset
|
939 self.nt.readonly.iter().map(|block| block.clone()).collect(); |
d2da8667125b
rust-nodemap: insert method
Georges Racinet <georges.racinet@octobus.net>
parents:
44261
diff
changeset
|
940 as_vec.extend(self.nt.growable); |
d2da8667125b
rust-nodemap: insert method
Georges Racinet <georges.racinet@octobus.net>
parents:
44261
diff
changeset
|
941 as_vec.push(self.nt.root); |
d2da8667125b
rust-nodemap: insert method
Georges Racinet <georges.racinet@octobus.net>
parents:
44261
diff
changeset
|
942 |
d2da8667125b
rust-nodemap: insert method
Georges Racinet <georges.racinet@octobus.net>
parents:
44261
diff
changeset
|
943 Self { |
d2da8667125b
rust-nodemap: insert method
Georges Racinet <georges.racinet@octobus.net>
parents:
44261
diff
changeset
|
944 index: self.index, |
d2da8667125b
rust-nodemap: insert method
Georges Racinet <georges.racinet@octobus.net>
parents:
44261
diff
changeset
|
945 nt: NodeTree::from(as_vec).into(), |
d2da8667125b
rust-nodemap: insert method
Georges Racinet <georges.racinet@octobus.net>
parents:
44261
diff
changeset
|
946 } |
d2da8667125b
rust-nodemap: insert method
Georges Racinet <georges.racinet@octobus.net>
parents:
44261
diff
changeset
|
947 } |
d2da8667125b
rust-nodemap: insert method
Georges Racinet <georges.racinet@octobus.net>
parents:
44261
diff
changeset
|
948 } |
d2da8667125b
rust-nodemap: insert method
Georges Racinet <georges.racinet@octobus.net>
parents:
44261
diff
changeset
|
949 |
d2da8667125b
rust-nodemap: insert method
Georges Racinet <georges.racinet@octobus.net>
parents:
44261
diff
changeset
|
950 #[test] |
d2da8667125b
rust-nodemap: insert method
Georges Racinet <georges.racinet@octobus.net>
parents:
44261
diff
changeset
|
951 fn test_insert_full_mutable() -> Result<(), NodeMapError> { |
d2da8667125b
rust-nodemap: insert method
Georges Racinet <georges.racinet@octobus.net>
parents:
44261
diff
changeset
|
952 let mut idx = TestNtIndex::new(); |
d2da8667125b
rust-nodemap: insert method
Georges Racinet <georges.racinet@octobus.net>
parents:
44261
diff
changeset
|
953 idx.insert(0, "1234")?; |
d2da8667125b
rust-nodemap: insert method
Georges Racinet <georges.racinet@octobus.net>
parents:
44261
diff
changeset
|
954 assert_eq!(idx.find_hex("1")?, Some(0)); |
d2da8667125b
rust-nodemap: insert method
Georges Racinet <georges.racinet@octobus.net>
parents:
44261
diff
changeset
|
955 assert_eq!(idx.find_hex("12")?, Some(0)); |
d2da8667125b
rust-nodemap: insert method
Georges Racinet <georges.racinet@octobus.net>
parents:
44261
diff
changeset
|
956 |
d2da8667125b
rust-nodemap: insert method
Georges Racinet <georges.racinet@octobus.net>
parents:
44261
diff
changeset
|
957 // let's trigger a simple split |
d2da8667125b
rust-nodemap: insert method
Georges Racinet <georges.racinet@octobus.net>
parents:
44261
diff
changeset
|
958 idx.insert(1, "1a34")?; |
d2da8667125b
rust-nodemap: insert method
Georges Racinet <georges.racinet@octobus.net>
parents:
44261
diff
changeset
|
959 assert_eq!(idx.nt.growable.len(), 1); |
d2da8667125b
rust-nodemap: insert method
Georges Racinet <georges.racinet@octobus.net>
parents:
44261
diff
changeset
|
960 assert_eq!(idx.find_hex("12")?, Some(0)); |
d2da8667125b
rust-nodemap: insert method
Georges Racinet <georges.racinet@octobus.net>
parents:
44261
diff
changeset
|
961 assert_eq!(idx.find_hex("1a")?, Some(1)); |
d2da8667125b
rust-nodemap: insert method
Georges Racinet <georges.racinet@octobus.net>
parents:
44261
diff
changeset
|
962 |
d2da8667125b
rust-nodemap: insert method
Georges Racinet <georges.racinet@octobus.net>
parents:
44261
diff
changeset
|
963 // reinserting is a no_op |
d2da8667125b
rust-nodemap: insert method
Georges Racinet <georges.racinet@octobus.net>
parents:
44261
diff
changeset
|
964 idx.insert(1, "1a34")?; |
d2da8667125b
rust-nodemap: insert method
Georges Racinet <georges.racinet@octobus.net>
parents:
44261
diff
changeset
|
965 assert_eq!(idx.nt.growable.len(), 1); |
d2da8667125b
rust-nodemap: insert method
Georges Racinet <georges.racinet@octobus.net>
parents:
44261
diff
changeset
|
966 assert_eq!(idx.find_hex("12")?, Some(0)); |
d2da8667125b
rust-nodemap: insert method
Georges Racinet <georges.racinet@octobus.net>
parents:
44261
diff
changeset
|
967 assert_eq!(idx.find_hex("1a")?, Some(1)); |
d2da8667125b
rust-nodemap: insert method
Georges Racinet <georges.racinet@octobus.net>
parents:
44261
diff
changeset
|
968 |
d2da8667125b
rust-nodemap: insert method
Georges Racinet <georges.racinet@octobus.net>
parents:
44261
diff
changeset
|
969 idx.insert(2, "1a01")?; |
d2da8667125b
rust-nodemap: insert method
Georges Racinet <georges.racinet@octobus.net>
parents:
44261
diff
changeset
|
970 assert_eq!(idx.nt.growable.len(), 2); |
d2da8667125b
rust-nodemap: insert method
Georges Racinet <georges.racinet@octobus.net>
parents:
44261
diff
changeset
|
971 assert_eq!(idx.find_hex("1a"), Err(NodeMapError::MultipleResults)); |
d2da8667125b
rust-nodemap: insert method
Georges Racinet <georges.racinet@octobus.net>
parents:
44261
diff
changeset
|
972 assert_eq!(idx.find_hex("12")?, Some(0)); |
d2da8667125b
rust-nodemap: insert method
Georges Racinet <georges.racinet@octobus.net>
parents:
44261
diff
changeset
|
973 assert_eq!(idx.find_hex("1a3")?, Some(1)); |
d2da8667125b
rust-nodemap: insert method
Georges Racinet <georges.racinet@octobus.net>
parents:
44261
diff
changeset
|
974 assert_eq!(idx.find_hex("1a0")?, Some(2)); |
d2da8667125b
rust-nodemap: insert method
Georges Racinet <georges.racinet@octobus.net>
parents:
44261
diff
changeset
|
975 assert_eq!(idx.find_hex("1a12")?, None); |
d2da8667125b
rust-nodemap: insert method
Georges Racinet <georges.racinet@octobus.net>
parents:
44261
diff
changeset
|
976 |
d2da8667125b
rust-nodemap: insert method
Georges Racinet <georges.racinet@octobus.net>
parents:
44261
diff
changeset
|
977 // now let's make it split and create more than one additional block |
d2da8667125b
rust-nodemap: insert method
Georges Racinet <georges.racinet@octobus.net>
parents:
44261
diff
changeset
|
978 idx.insert(3, "1a345")?; |
d2da8667125b
rust-nodemap: insert method
Georges Racinet <georges.racinet@octobus.net>
parents:
44261
diff
changeset
|
979 assert_eq!(idx.nt.growable.len(), 4); |
d2da8667125b
rust-nodemap: insert method
Georges Racinet <georges.racinet@octobus.net>
parents:
44261
diff
changeset
|
980 assert_eq!(idx.find_hex("1a340")?, Some(1)); |
d2da8667125b
rust-nodemap: insert method
Georges Racinet <georges.racinet@octobus.net>
parents:
44261
diff
changeset
|
981 assert_eq!(idx.find_hex("1a345")?, Some(3)); |
d2da8667125b
rust-nodemap: insert method
Georges Racinet <georges.racinet@octobus.net>
parents:
44261
diff
changeset
|
982 assert_eq!(idx.find_hex("1a341")?, None); |
d2da8667125b
rust-nodemap: insert method
Georges Racinet <georges.racinet@octobus.net>
parents:
44261
diff
changeset
|
983 |
44420
6329ce04c69f
rust-nodemap: accounting for dead blocks
Georges Racinet <georges.racinet@octobus.net>
parents:
44419
diff
changeset
|
984 // there's no readonly block to mask |
6329ce04c69f
rust-nodemap: accounting for dead blocks
Georges Racinet <georges.racinet@octobus.net>
parents:
44419
diff
changeset
|
985 assert_eq!(idx.nt.masked_readonly_blocks(), 0); |
44390
d2da8667125b
rust-nodemap: insert method
Georges Racinet <georges.racinet@octobus.net>
parents:
44261
diff
changeset
|
986 Ok(()) |
d2da8667125b
rust-nodemap: insert method
Georges Racinet <georges.racinet@octobus.net>
parents:
44261
diff
changeset
|
987 } |
d2da8667125b
rust-nodemap: insert method
Georges Racinet <georges.racinet@octobus.net>
parents:
44261
diff
changeset
|
988 |
d2da8667125b
rust-nodemap: insert method
Georges Racinet <georges.racinet@octobus.net>
parents:
44261
diff
changeset
|
989 #[test] |
44419
5ac1eecc9c64
rust-nodemap: core implementation for shortest
Georges Racinet <georges.racinet@octobus.net>
parents:
44418
diff
changeset
|
990 fn test_unique_prefix_len_zero_prefix() { |
5ac1eecc9c64
rust-nodemap: core implementation for shortest
Georges Racinet <georges.racinet@octobus.net>
parents:
44418
diff
changeset
|
991 let mut idx = TestNtIndex::new(); |
5ac1eecc9c64
rust-nodemap: core implementation for shortest
Georges Racinet <georges.racinet@octobus.net>
parents:
44418
diff
changeset
|
992 idx.insert(0, "00000abcd").unwrap(); |
5ac1eecc9c64
rust-nodemap: core implementation for shortest
Georges Racinet <georges.racinet@octobus.net>
parents:
44418
diff
changeset
|
993 |
5ac1eecc9c64
rust-nodemap: core implementation for shortest
Georges Racinet <georges.racinet@octobus.net>
parents:
44418
diff
changeset
|
994 assert_eq!(idx.find_hex("000"), Err(NodeMapError::MultipleResults)); |
5ac1eecc9c64
rust-nodemap: core implementation for shortest
Georges Racinet <georges.racinet@octobus.net>
parents:
44418
diff
changeset
|
995 // in the nodetree proper, this will be found at the first nybble |
5ac1eecc9c64
rust-nodemap: core implementation for shortest
Georges Racinet <georges.racinet@octobus.net>
parents:
44418
diff
changeset
|
996 // yet the correct answer for unique_prefix_len is not 1, nor 1+1, |
5ac1eecc9c64
rust-nodemap: core implementation for shortest
Georges Racinet <georges.racinet@octobus.net>
parents:
44418
diff
changeset
|
997 // but the first difference with `NULL_NODE` |
5ac1eecc9c64
rust-nodemap: core implementation for shortest
Georges Racinet <georges.racinet@octobus.net>
parents:
44418
diff
changeset
|
998 assert_eq!(idx.unique_prefix_len_hex("00000a"), Ok(Some(6))); |
5ac1eecc9c64
rust-nodemap: core implementation for shortest
Georges Racinet <georges.racinet@octobus.net>
parents:
44418
diff
changeset
|
999 assert_eq!(idx.unique_prefix_len_hex("00000ab"), Ok(Some(6))); |
5ac1eecc9c64
rust-nodemap: core implementation for shortest
Georges Racinet <georges.racinet@octobus.net>
parents:
44418
diff
changeset
|
1000 |
5ac1eecc9c64
rust-nodemap: core implementation for shortest
Georges Racinet <georges.racinet@octobus.net>
parents:
44418
diff
changeset
|
1001 // same with odd result |
5ac1eecc9c64
rust-nodemap: core implementation for shortest
Georges Racinet <georges.racinet@octobus.net>
parents:
44418
diff
changeset
|
1002 idx.insert(1, "00123").unwrap(); |
5ac1eecc9c64
rust-nodemap: core implementation for shortest
Georges Racinet <georges.racinet@octobus.net>
parents:
44418
diff
changeset
|
1003 assert_eq!(idx.unique_prefix_len_hex("001"), Ok(Some(3))); |
5ac1eecc9c64
rust-nodemap: core implementation for shortest
Georges Racinet <georges.racinet@octobus.net>
parents:
44418
diff
changeset
|
1004 assert_eq!(idx.unique_prefix_len_hex("0012"), Ok(Some(3))); |
5ac1eecc9c64
rust-nodemap: core implementation for shortest
Georges Racinet <georges.racinet@octobus.net>
parents:
44418
diff
changeset
|
1005 |
5ac1eecc9c64
rust-nodemap: core implementation for shortest
Georges Racinet <georges.racinet@octobus.net>
parents:
44418
diff
changeset
|
1006 // these are unchanged of course |
5ac1eecc9c64
rust-nodemap: core implementation for shortest
Georges Racinet <georges.racinet@octobus.net>
parents:
44418
diff
changeset
|
1007 assert_eq!(idx.unique_prefix_len_hex("00000a"), Ok(Some(6))); |
5ac1eecc9c64
rust-nodemap: core implementation for shortest
Georges Racinet <georges.racinet@octobus.net>
parents:
44418
diff
changeset
|
1008 assert_eq!(idx.unique_prefix_len_hex("00000ab"), Ok(Some(6))); |
5ac1eecc9c64
rust-nodemap: core implementation for shortest
Georges Racinet <georges.racinet@octobus.net>
parents:
44418
diff
changeset
|
1009 } |
5ac1eecc9c64
rust-nodemap: core implementation for shortest
Georges Racinet <georges.racinet@octobus.net>
parents:
44418
diff
changeset
|
1010 |
5ac1eecc9c64
rust-nodemap: core implementation for shortest
Georges Racinet <georges.racinet@octobus.net>
parents:
44418
diff
changeset
|
1011 #[test] |
44390
d2da8667125b
rust-nodemap: insert method
Georges Racinet <georges.racinet@octobus.net>
parents:
44261
diff
changeset
|
1012 fn test_insert_extreme_splitting() -> Result<(), NodeMapError> { |
d2da8667125b
rust-nodemap: insert method
Georges Racinet <georges.racinet@octobus.net>
parents:
44261
diff
changeset
|
1013 // check that the splitting loop is long enough |
d2da8667125b
rust-nodemap: insert method
Georges Racinet <georges.racinet@octobus.net>
parents:
44261
diff
changeset
|
1014 let mut nt_idx = TestNtIndex::new(); |
d2da8667125b
rust-nodemap: insert method
Georges Racinet <georges.racinet@octobus.net>
parents:
44261
diff
changeset
|
1015 let nt = &mut nt_idx.nt; |
d2da8667125b
rust-nodemap: insert method
Georges Racinet <georges.racinet@octobus.net>
parents:
44261
diff
changeset
|
1016 let idx = &mut nt_idx.index; |
d2da8667125b
rust-nodemap: insert method
Georges Racinet <georges.racinet@octobus.net>
parents:
44261
diff
changeset
|
1017 |
d2da8667125b
rust-nodemap: insert method
Georges Racinet <georges.racinet@octobus.net>
parents:
44261
diff
changeset
|
1018 let node0_hex = hex_pad_right("444444"); |
d2da8667125b
rust-nodemap: insert method
Georges Racinet <georges.racinet@octobus.net>
parents:
44261
diff
changeset
|
1019 let mut node1_hex = hex_pad_right("444444").clone(); |
d2da8667125b
rust-nodemap: insert method
Georges Racinet <georges.racinet@octobus.net>
parents:
44261
diff
changeset
|
1020 node1_hex.pop(); |
d2da8667125b
rust-nodemap: insert method
Georges Racinet <georges.racinet@octobus.net>
parents:
44261
diff
changeset
|
1021 node1_hex.push('5'); |
d2da8667125b
rust-nodemap: insert method
Georges Racinet <georges.racinet@octobus.net>
parents:
44261
diff
changeset
|
1022 let node0 = Node::from_hex(&node0_hex).unwrap(); |
d2da8667125b
rust-nodemap: insert method
Georges Racinet <georges.racinet@octobus.net>
parents:
44261
diff
changeset
|
1023 let node1 = Node::from_hex(&node1_hex).unwrap(); |
d2da8667125b
rust-nodemap: insert method
Georges Racinet <georges.racinet@octobus.net>
parents:
44261
diff
changeset
|
1024 |
d2da8667125b
rust-nodemap: insert method
Georges Racinet <georges.racinet@octobus.net>
parents:
44261
diff
changeset
|
1025 idx.insert(0, node0.clone()); |
d2da8667125b
rust-nodemap: insert method
Georges Racinet <georges.racinet@octobus.net>
parents:
44261
diff
changeset
|
1026 nt.insert(idx, &node0, 0)?; |
d2da8667125b
rust-nodemap: insert method
Georges Racinet <georges.racinet@octobus.net>
parents:
44261
diff
changeset
|
1027 idx.insert(1, node1.clone()); |
d2da8667125b
rust-nodemap: insert method
Georges Racinet <georges.racinet@octobus.net>
parents:
44261
diff
changeset
|
1028 nt.insert(idx, &node1, 1)?; |
d2da8667125b
rust-nodemap: insert method
Georges Racinet <georges.racinet@octobus.net>
parents:
44261
diff
changeset
|
1029 |
d2da8667125b
rust-nodemap: insert method
Georges Racinet <georges.racinet@octobus.net>
parents:
44261
diff
changeset
|
1030 assert_eq!(nt.find_bin(idx, (&node0).into())?, Some(0)); |
d2da8667125b
rust-nodemap: insert method
Georges Racinet <georges.racinet@octobus.net>
parents:
44261
diff
changeset
|
1031 assert_eq!(nt.find_bin(idx, (&node1).into())?, Some(1)); |
d2da8667125b
rust-nodemap: insert method
Georges Racinet <georges.racinet@octobus.net>
parents:
44261
diff
changeset
|
1032 Ok(()) |
d2da8667125b
rust-nodemap: insert method
Georges Racinet <georges.racinet@octobus.net>
parents:
44261
diff
changeset
|
1033 } |
d2da8667125b
rust-nodemap: insert method
Georges Racinet <georges.racinet@octobus.net>
parents:
44261
diff
changeset
|
1034 |
d2da8667125b
rust-nodemap: insert method
Georges Racinet <georges.racinet@octobus.net>
parents:
44261
diff
changeset
|
1035 #[test] |
d2da8667125b
rust-nodemap: insert method
Georges Racinet <georges.racinet@octobus.net>
parents:
44261
diff
changeset
|
1036 fn test_insert_partly_immutable() -> Result<(), NodeMapError> { |
d2da8667125b
rust-nodemap: insert method
Georges Racinet <georges.racinet@octobus.net>
parents:
44261
diff
changeset
|
1037 let mut idx = TestNtIndex::new(); |
d2da8667125b
rust-nodemap: insert method
Georges Racinet <georges.racinet@octobus.net>
parents:
44261
diff
changeset
|
1038 idx.insert(0, "1234")?; |
d2da8667125b
rust-nodemap: insert method
Georges Racinet <georges.racinet@octobus.net>
parents:
44261
diff
changeset
|
1039 idx.insert(1, "1235")?; |
d2da8667125b
rust-nodemap: insert method
Georges Racinet <georges.racinet@octobus.net>
parents:
44261
diff
changeset
|
1040 idx.insert(2, "131")?; |
d2da8667125b
rust-nodemap: insert method
Georges Racinet <georges.racinet@octobus.net>
parents:
44261
diff
changeset
|
1041 idx.insert(3, "cafe")?; |
d2da8667125b
rust-nodemap: insert method
Georges Racinet <georges.racinet@octobus.net>
parents:
44261
diff
changeset
|
1042 let mut idx = idx.commit(); |
d2da8667125b
rust-nodemap: insert method
Georges Racinet <georges.racinet@octobus.net>
parents:
44261
diff
changeset
|
1043 assert_eq!(idx.find_hex("1234")?, Some(0)); |
d2da8667125b
rust-nodemap: insert method
Georges Racinet <georges.racinet@octobus.net>
parents:
44261
diff
changeset
|
1044 assert_eq!(idx.find_hex("1235")?, Some(1)); |
d2da8667125b
rust-nodemap: insert method
Georges Racinet <georges.racinet@octobus.net>
parents:
44261
diff
changeset
|
1045 assert_eq!(idx.find_hex("131")?, Some(2)); |
d2da8667125b
rust-nodemap: insert method
Georges Racinet <georges.racinet@octobus.net>
parents:
44261
diff
changeset
|
1046 assert_eq!(idx.find_hex("cafe")?, Some(3)); |
44420
6329ce04c69f
rust-nodemap: accounting for dead blocks
Georges Racinet <georges.racinet@octobus.net>
parents:
44419
diff
changeset
|
1047 // we did not add anything since init from readonly |
6329ce04c69f
rust-nodemap: accounting for dead blocks
Georges Racinet <georges.racinet@octobus.net>
parents:
44419
diff
changeset
|
1048 assert_eq!(idx.nt.masked_readonly_blocks(), 0); |
44390
d2da8667125b
rust-nodemap: insert method
Georges Racinet <georges.racinet@octobus.net>
parents:
44261
diff
changeset
|
1049 |
d2da8667125b
rust-nodemap: insert method
Georges Racinet <georges.racinet@octobus.net>
parents:
44261
diff
changeset
|
1050 idx.insert(4, "123A")?; |
d2da8667125b
rust-nodemap: insert method
Georges Racinet <georges.racinet@octobus.net>
parents:
44261
diff
changeset
|
1051 assert_eq!(idx.find_hex("1234")?, Some(0)); |
d2da8667125b
rust-nodemap: insert method
Georges Racinet <georges.racinet@octobus.net>
parents:
44261
diff
changeset
|
1052 assert_eq!(idx.find_hex("1235")?, Some(1)); |
d2da8667125b
rust-nodemap: insert method
Georges Racinet <georges.racinet@octobus.net>
parents:
44261
diff
changeset
|
1053 assert_eq!(idx.find_hex("131")?, Some(2)); |
d2da8667125b
rust-nodemap: insert method
Georges Racinet <georges.racinet@octobus.net>
parents:
44261
diff
changeset
|
1054 assert_eq!(idx.find_hex("cafe")?, Some(3)); |
d2da8667125b
rust-nodemap: insert method
Georges Racinet <georges.racinet@octobus.net>
parents:
44261
diff
changeset
|
1055 assert_eq!(idx.find_hex("123A")?, Some(4)); |
44420
6329ce04c69f
rust-nodemap: accounting for dead blocks
Georges Racinet <georges.racinet@octobus.net>
parents:
44419
diff
changeset
|
1056 // we masked blocks for all prefixes of "123", including the root |
6329ce04c69f
rust-nodemap: accounting for dead blocks
Georges Racinet <georges.racinet@octobus.net>
parents:
44419
diff
changeset
|
1057 assert_eq!(idx.nt.masked_readonly_blocks(), 4); |
44390
d2da8667125b
rust-nodemap: insert method
Georges Racinet <georges.racinet@octobus.net>
parents:
44261
diff
changeset
|
1058 |
44420
6329ce04c69f
rust-nodemap: accounting for dead blocks
Georges Racinet <georges.racinet@octobus.net>
parents:
44419
diff
changeset
|
1059 eprintln!("{:?}", idx.nt); |
44390
d2da8667125b
rust-nodemap: insert method
Georges Racinet <georges.racinet@octobus.net>
parents:
44261
diff
changeset
|
1060 idx.insert(5, "c0")?; |
d2da8667125b
rust-nodemap: insert method
Georges Racinet <georges.racinet@octobus.net>
parents:
44261
diff
changeset
|
1061 assert_eq!(idx.find_hex("cafe")?, Some(3)); |
d2da8667125b
rust-nodemap: insert method
Georges Racinet <georges.racinet@octobus.net>
parents:
44261
diff
changeset
|
1062 assert_eq!(idx.find_hex("c0")?, Some(5)); |
d2da8667125b
rust-nodemap: insert method
Georges Racinet <georges.racinet@octobus.net>
parents:
44261
diff
changeset
|
1063 assert_eq!(idx.find_hex("c1")?, None); |
d2da8667125b
rust-nodemap: insert method
Georges Racinet <georges.racinet@octobus.net>
parents:
44261
diff
changeset
|
1064 assert_eq!(idx.find_hex("1234")?, Some(0)); |
44420
6329ce04c69f
rust-nodemap: accounting for dead blocks
Georges Racinet <georges.racinet@octobus.net>
parents:
44419
diff
changeset
|
1065 // inserting "c0" is just splitting the 'c' slot of the mutable root, |
6329ce04c69f
rust-nodemap: accounting for dead blocks
Georges Racinet <georges.racinet@octobus.net>
parents:
44419
diff
changeset
|
1066 // it doesn't mask anything |
6329ce04c69f
rust-nodemap: accounting for dead blocks
Georges Racinet <georges.racinet@octobus.net>
parents:
44419
diff
changeset
|
1067 assert_eq!(idx.nt.masked_readonly_blocks(), 4); |
44390
d2da8667125b
rust-nodemap: insert method
Georges Racinet <georges.racinet@octobus.net>
parents:
44261
diff
changeset
|
1068 |
d2da8667125b
rust-nodemap: insert method
Georges Racinet <georges.racinet@octobus.net>
parents:
44261
diff
changeset
|
1069 Ok(()) |
d2da8667125b
rust-nodemap: insert method
Georges Racinet <georges.racinet@octobus.net>
parents:
44261
diff
changeset
|
1070 } |
44416
a98ba6983a63
rust-nodemap: input/output primitives
Georges Racinet <georges.racinet@octobus.net>
parents:
44390
diff
changeset
|
1071 |
a98ba6983a63
rust-nodemap: input/output primitives
Georges Racinet <georges.racinet@octobus.net>
parents:
44390
diff
changeset
|
1072 #[test] |
44421
d518994384a4
rust-nodemap: a method for full invalidation
Georges Racinet <georges.racinet@octobus.net>
parents:
44420
diff
changeset
|
1073 fn test_invalidate_all() -> Result<(), NodeMapError> { |
d518994384a4
rust-nodemap: a method for full invalidation
Georges Racinet <georges.racinet@octobus.net>
parents:
44420
diff
changeset
|
1074 let mut idx = TestNtIndex::new(); |
d518994384a4
rust-nodemap: a method for full invalidation
Georges Racinet <georges.racinet@octobus.net>
parents:
44420
diff
changeset
|
1075 idx.insert(0, "1234")?; |
d518994384a4
rust-nodemap: a method for full invalidation
Georges Racinet <georges.racinet@octobus.net>
parents:
44420
diff
changeset
|
1076 idx.insert(1, "1235")?; |
d518994384a4
rust-nodemap: a method for full invalidation
Georges Racinet <georges.racinet@octobus.net>
parents:
44420
diff
changeset
|
1077 idx.insert(2, "131")?; |
d518994384a4
rust-nodemap: a method for full invalidation
Georges Racinet <georges.racinet@octobus.net>
parents:
44420
diff
changeset
|
1078 idx.insert(3, "cafe")?; |
d518994384a4
rust-nodemap: a method for full invalidation
Georges Racinet <georges.racinet@octobus.net>
parents:
44420
diff
changeset
|
1079 let mut idx = idx.commit(); |
d518994384a4
rust-nodemap: a method for full invalidation
Georges Racinet <georges.racinet@octobus.net>
parents:
44420
diff
changeset
|
1080 |
d518994384a4
rust-nodemap: a method for full invalidation
Georges Racinet <georges.racinet@octobus.net>
parents:
44420
diff
changeset
|
1081 idx.nt.invalidate_all(); |
d518994384a4
rust-nodemap: a method for full invalidation
Georges Racinet <georges.racinet@octobus.net>
parents:
44420
diff
changeset
|
1082 |
d518994384a4
rust-nodemap: a method for full invalidation
Georges Racinet <georges.racinet@octobus.net>
parents:
44420
diff
changeset
|
1083 assert_eq!(idx.find_hex("1234")?, None); |
d518994384a4
rust-nodemap: a method for full invalidation
Georges Racinet <georges.racinet@octobus.net>
parents:
44420
diff
changeset
|
1084 assert_eq!(idx.find_hex("1235")?, None); |
d518994384a4
rust-nodemap: a method for full invalidation
Georges Racinet <georges.racinet@octobus.net>
parents:
44420
diff
changeset
|
1085 assert_eq!(idx.find_hex("131")?, None); |
d518994384a4
rust-nodemap: a method for full invalidation
Georges Racinet <georges.racinet@octobus.net>
parents:
44420
diff
changeset
|
1086 assert_eq!(idx.find_hex("cafe")?, None); |
d518994384a4
rust-nodemap: a method for full invalidation
Georges Racinet <georges.racinet@octobus.net>
parents:
44420
diff
changeset
|
1087 // all the readonly blocks have been masked, this is the |
d518994384a4
rust-nodemap: a method for full invalidation
Georges Racinet <georges.racinet@octobus.net>
parents:
44420
diff
changeset
|
1088 // conventional expected response |
d518994384a4
rust-nodemap: a method for full invalidation
Georges Racinet <georges.racinet@octobus.net>
parents:
44420
diff
changeset
|
1089 assert_eq!(idx.nt.masked_readonly_blocks(), idx.nt.readonly.len() + 1); |
d518994384a4
rust-nodemap: a method for full invalidation
Georges Racinet <georges.racinet@octobus.net>
parents:
44420
diff
changeset
|
1090 Ok(()) |
d518994384a4
rust-nodemap: a method for full invalidation
Georges Racinet <georges.racinet@octobus.net>
parents:
44420
diff
changeset
|
1091 } |
d518994384a4
rust-nodemap: a method for full invalidation
Georges Racinet <georges.racinet@octobus.net>
parents:
44420
diff
changeset
|
1092 |
d518994384a4
rust-nodemap: a method for full invalidation
Georges Racinet <georges.racinet@octobus.net>
parents:
44420
diff
changeset
|
1093 #[test] |
44416
a98ba6983a63
rust-nodemap: input/output primitives
Georges Racinet <georges.racinet@octobus.net>
parents:
44390
diff
changeset
|
1094 fn test_into_added_empty() { |
a98ba6983a63
rust-nodemap: input/output primitives
Georges Racinet <georges.racinet@octobus.net>
parents:
44390
diff
changeset
|
1095 assert!(sample_nodetree().into_readonly_and_added().1.is_empty()); |
a98ba6983a63
rust-nodemap: input/output primitives
Georges Racinet <georges.racinet@octobus.net>
parents:
44390
diff
changeset
|
1096 assert!(sample_nodetree() |
a98ba6983a63
rust-nodemap: input/output primitives
Georges Racinet <georges.racinet@octobus.net>
parents:
44390
diff
changeset
|
1097 .into_readonly_and_added_bytes() |
a98ba6983a63
rust-nodemap: input/output primitives
Georges Racinet <georges.racinet@octobus.net>
parents:
44390
diff
changeset
|
1098 .1 |
a98ba6983a63
rust-nodemap: input/output primitives
Georges Racinet <georges.racinet@octobus.net>
parents:
44390
diff
changeset
|
1099 .is_empty()); |
a98ba6983a63
rust-nodemap: input/output primitives
Georges Racinet <georges.racinet@octobus.net>
parents:
44390
diff
changeset
|
1100 } |
a98ba6983a63
rust-nodemap: input/output primitives
Georges Racinet <georges.racinet@octobus.net>
parents:
44390
diff
changeset
|
1101 |
a98ba6983a63
rust-nodemap: input/output primitives
Georges Racinet <georges.racinet@octobus.net>
parents:
44390
diff
changeset
|
1102 #[test] |
a98ba6983a63
rust-nodemap: input/output primitives
Georges Racinet <georges.racinet@octobus.net>
parents:
44390
diff
changeset
|
1103 fn test_into_added_bytes() -> Result<(), NodeMapError> { |
a98ba6983a63
rust-nodemap: input/output primitives
Georges Racinet <georges.racinet@octobus.net>
parents:
44390
diff
changeset
|
1104 let mut idx = TestNtIndex::new(); |
a98ba6983a63
rust-nodemap: input/output primitives
Georges Racinet <georges.racinet@octobus.net>
parents:
44390
diff
changeset
|
1105 idx.insert(0, "1234")?; |
a98ba6983a63
rust-nodemap: input/output primitives
Georges Racinet <georges.racinet@octobus.net>
parents:
44390
diff
changeset
|
1106 let mut idx = idx.commit(); |
a98ba6983a63
rust-nodemap: input/output primitives
Georges Racinet <georges.racinet@octobus.net>
parents:
44390
diff
changeset
|
1107 idx.insert(4, "cafe")?; |
a98ba6983a63
rust-nodemap: input/output primitives
Georges Racinet <georges.racinet@octobus.net>
parents:
44390
diff
changeset
|
1108 let (_, bytes) = idx.nt.into_readonly_and_added_bytes(); |
a98ba6983a63
rust-nodemap: input/output primitives
Georges Racinet <georges.racinet@octobus.net>
parents:
44390
diff
changeset
|
1109 |
a98ba6983a63
rust-nodemap: input/output primitives
Georges Racinet <georges.racinet@octobus.net>
parents:
44390
diff
changeset
|
1110 // only the root block has been changed |
a98ba6983a63
rust-nodemap: input/output primitives
Georges Racinet <georges.racinet@octobus.net>
parents:
44390
diff
changeset
|
1111 assert_eq!(bytes.len(), BLOCK_SIZE); |
a98ba6983a63
rust-nodemap: input/output primitives
Georges Racinet <georges.racinet@octobus.net>
parents:
44390
diff
changeset
|
1112 // big endian for -2 |
a98ba6983a63
rust-nodemap: input/output primitives
Georges Racinet <georges.racinet@octobus.net>
parents:
44390
diff
changeset
|
1113 assert_eq!(&bytes[4..2 * 4], [255, 255, 255, 254]); |
a98ba6983a63
rust-nodemap: input/output primitives
Georges Racinet <georges.racinet@octobus.net>
parents:
44390
diff
changeset
|
1114 // big endian for -6 |
a98ba6983a63
rust-nodemap: input/output primitives
Georges Racinet <georges.racinet@octobus.net>
parents:
44390
diff
changeset
|
1115 assert_eq!(&bytes[12 * 4..13 * 4], [255, 255, 255, 250]); |
a98ba6983a63
rust-nodemap: input/output primitives
Georges Racinet <georges.racinet@octobus.net>
parents:
44390
diff
changeset
|
1116 Ok(()) |
a98ba6983a63
rust-nodemap: input/output primitives
Georges Racinet <georges.racinet@octobus.net>
parents:
44390
diff
changeset
|
1117 } |
44227
63db6657d280
rust-nodemap: building blocks for nodetree structures
Georges Racinet <georges.racinet@octobus.net>
parents:
diff
changeset
|
1118 } |