annotate rust/hg-core/src/revlog/node.rs @ 45986:cc759d3db1e8

copies-rust: leverage the immutability for efficient update The immutable OrdMap has a diff function. That function yield items for each difference (missing in minor; missing in major; present in both, but different). We reorganise the manifest merging code to use this new function. We gather the data we would need to inject into the `minor` or `major` dict and eventually update one of them. The semantic of the merge itself is kept as is. Why are we doing this? Last year we contributed a patch making that diff function quickly detect some of the identical subsection when comparing two OrdMap cloned from a common ancestors (because they point to the very same node in memory). As a result: - That diff function is very fast in most of our cases, - It is important to maximize the "common" part by minimising the amount of unnecessary changes we do in theses Map. This is why we gather update for both and update the one with the smaller update. In practice, this yield a massive speed up on all our slow cases. Some examples below.: Repo Cases Source-Rev Dest-Rev Old-Time New-Time Difference Factor ------------------------------------------------------------------------------------------------------------------------------------ pypy x0000_revs_x_added_0_copies d1defd0dc478 c9cb1334cc78 : 33.527067 s, 2.780174 s, -30.746893 s, ? 0.0829 netbeans x0000_revs_xx000_added_x000_copies 588c2d1ced70 1aad62e59ddd : killed(>120), 1.231869 s mozilla-central x00000_revs_x0000_added_x0000_copies 6832ae71433c 4c222a1d9a00 : killed(>120), 3.478747 s mozilla-try x0000_revs_xx000_added_x000_copies 89294cd501d9 7ccb2fc7ccb5 : 83.508590 s, 9.843481 s, -73.665109 s, ? 0.1179 mozilla-try x0000_revs_x0000_added_x0000_copies e928c65095ed e951f4ad123a : 55.079813 s, 1.465128 s, -53.614685 s, ? 0.0266 The performance compared to the Python code are now comparable (worst case are a score percent slower)" You an check the full table below for details. The big new is that, with this change, we are now faster filelog in most case, . Below is an highlight of some pretty nice win: Repo Case Source-Rev Dest-Rev filelog sidedata Difference Factor --------------------------------------------------------------------------------------------------------------------------------------- pypy x0000_revs_xx000_added_x000_copies 08ea3258278e d9fa043f30c0 : 1.354211 s, 0.252125 s, -1.102086 s, ? 0.186179 netbeans x000_revs_x000_added_x000_copies ff453e9fee32 411350406ec2 : 0.939593 s, 0.112534 s, -0.827059 s, ? 0.119769 netbeans x0000_revs_xx000_added_x000_copies 588c2d1ced70 1aad62e59ddd : 3.824967 s, 1.231869 s, -2.593098 s, ? 0.322060 mozilla-central x000_revs_x000_added_x000_copies 7c97034feb78 4407bd0c6330 : 1.142414 s, 0.102184 s, -1.040230 s, ? 0.089446 mozilla-central x0000_revs_xx000_added_0_copies 9eec5917337d 67118cc6dcad : 6.667504 s, 0.046220 s, -6.621284 s, ? 0.006932 mozilla-central x0000_revs_xx000_added_x000_copies f78c615a656c 96a38b690156 : 3.267274 s, 0.315271 s, -2.952003 s, ? 0.096494 mozilla-central x00000_revs_x0000_added_x0000_copies 6832ae71433c 4c222a1d9a00 : 16.038104 s, 3.478747 s, -12.559357 s, ? 0.216905 mozilla-central x00000_revs_x00000_added_x000_copies 76caed42cf7c 1daa622bbe42 : 20.639928 s, 4.766435 s, -15.873493 s, ? 0.230933 They they are a handful of slower case where we perform less well. A good Share of them are really pathological "service" merge in mozilla-try, but not all of them. Repo Case Source-Rev Dest-Rev filelog sidedata Difference Factor --------------------------------------------------------------------------------------------------------------------------------------- pypy x0000_revs_x_added_0_copies d1defd0dc478 c9cb1334cc78 : 0.001055 s, 2.780174 s, +2.779119 s, ? 2635.236019 mozilla-try x0000_revs_x_added_0_copies 63519bfd42ee a36a2a865d92 : 0.088715 s, 0.435381 s, +0.346666 s, ? 4.907637 mozilla-try x0000_revs_x_added_x_copies 9fe69ff0762d bcabf2a78927 : 0.080765 s, 0.415461 s, +0.334696 s, ? 5.144072 mozilla-try x0000_revs_xx000_added_x000_copies 89294cd501d9 7ccb2fc7ccb5 : 7.598509 s, 9.843481 s, +2.244972 s, ? 1.295449 mozilla-try x00000_revs_x_added_0_copies 6a320851d377 1ebb79acd503 : 0.092232 s, killed mozilla-try x00000_revs_x_added_x_copies 5173c4b6f97c 95d83ee7242d : 0.093892 s, killed mozilla-try x00000_revs_x000_added_x_copies 9126823d0e9c ca82787bb23c : 0.227503 s, killed mozilla-try x00000_revs_x00000_added_x0000_copies 1b661134e2ca 1ae03d022d6d : 21.145391 s, killed mozilla-try x00000_revs_x00000_added_x000_copies 9b2a99adc05e 8e29777b48e6 : 25.304164 s, killed Below are two different tables for full performance comparison - this changeset against the previous one (spoiler: it is much better) - this changeset against the python code (spoiler: still slower, but it gets more comparable) - this changeset against the filelog code (spoiler: better in many case, but not all) Repo Cases Source-Rev Dest-Rev Old-Time New-Time Difference Factor ------------------------------------------------------------------------------------------------------------------------------------ mercurial x_revs_x_added_0_copies ad6b123de1c7 39cfcef4f463 : 0.000049 s, 0.000049 s, +0.000000 s, ? 1.0000 mercurial x_revs_x_added_x_copies 2b1c78674230 0c1d10351869 : 0.000179 s, 0.000182 s, +0.000003 s, ? 1.0168 mercurial x000_revs_x000_added_x_copies 81f8ff2a9bf2 dd3267698d84 : 0.006494 s, 0.005872 s, -0.000622 s, ? 0.9042 pypy x_revs_x_added_0_copies aed021ee8ae8 099ed31b181b : 0.000339 s, 0.000229 s, -0.000110 s, ? 0.6755 pypy x_revs_x000_added_0_copies 4aa4e1f8e19a 359343b9ac0e : 0.000057 s, 0.000058 s, +0.000001 s, ? 1.0175 pypy x_revs_x_added_x_copies ac52eb7bbbb0 72e022663155 : 0.000299 s, 0.000148 s, -0.000151 s, ? 0.4950 pypy x_revs_x00_added_x_copies c3b14617fbd7 ace7255d9a26 : 0.001200 s, 0.001205 s, +0.000005 s, ? 1.0042 pypy x_revs_x000_added_x000_copies df6f7a526b60 a83dc6a2d56f : 0.025120 s, 0.025662 s, +0.000542 s, ? 1.0216 pypy x000_revs_xx00_added_0_copies 89a76aede314 2f22446ff07e : 0.506921 s, 0.080113 s, -0.426808 s, ? 0.1580 pypy x000_revs_x000_added_x_copies 8a3b5bfd266e 2c68e87c3efe : 1.272060 s, 0.153030 s, -1.119030 s, ? 0.1203 pypy x000_revs_x000_added_x000_copies 89a76aede314 7b3dda341c84 : 0.690941 s, 0.098774 s, -0.592167 s, ? 0.1430 pypy x0000_revs_x_added_0_copies d1defd0dc478 c9cb1334cc78 : 33.527067 s, 2.780174 s, -30.746893 s, ? 0.0829 pypy x0000_revs_xx000_added_0_copies bf2c629d0071 4ffed77c095c : 0.021970 s, 0.022218 s, +0.000248 s, ? 1.0113 pypy x0000_revs_xx000_added_x000_copies 08ea3258278e d9fa043f30c0 : 1.772094 s, 0.252125 s, -1.519969 s, ? 0.1423 netbeans x_revs_x_added_0_copies fb0955ffcbcd a01e9239f9e7 : 0.000185 s, 0.000186 s, +0.000001 s, ? 1.0054 netbeans x_revs_x000_added_0_copies 6f360122949f 20eb231cc7d0 : 0.000135 s, 0.000133 s, -0.000002 s, ? 0.9852 netbeans x_revs_x_added_x_copies 1ada3faf6fb6 5a39d12eecf4 : 0.000329 s, 0.000320 s, -0.000009 s, ? 0.9726 netbeans x_revs_x00_added_x_copies 35be93ba1e2c 9eec5e90c05f : 0.001343 s, 0.001336 s, -0.000007 s, ? 0.9948 netbeans x000_revs_xx00_added_0_copies eac3045b4fdd 51d4ae7f1290 : 0.029396 s, 0.015573 s, -0.013823 s, ? 0.5298 netbeans x000_revs_x000_added_x_copies e2063d266acd 6081d72689dc : 0.040210 s, 0.018667 s, -0.021543 s, ? 0.4642 netbeans x000_revs_x000_added_x000_copies ff453e9fee32 411350406ec2 : 4.556794 s, 0.112534 s, -4.444260 s, ? 0.0247 netbeans x0000_revs_xx000_added_x000_copies 588c2d1ced70 1aad62e59ddd : killed , 1.231869 s mozilla-central x_revs_x_added_0_copies 3697f962bb7b 7015fcdd43a2 : 0.000199 s, 0.000197 s, -0.000002 s, ? 0.9899 mozilla-central x_revs_x000_added_0_copies dd390860c6c9 40d0c5bed75d : 0.000639 s, 0.000637 s, -0.000002 s, ? 0.9969 mozilla-central x_revs_x_added_x_copies 8d198483ae3b 14207ffc2b2f : 0.000542 s, 0.000303 s, -0.000239 s, ? 0.5590 mozilla-central x_revs_x00_added_x_copies 98cbc58cc6bc 446a150332c3 : 0.001685 s, 0.001663 s, -0.000022 s, ? 0.9869 mozilla-central x_revs_x000_added_x000_copies 3c684b4b8f68 0a5e72d1b479 : 0.006954 s, 0.007008 s, +0.000054 s, ? 1.0078 mozilla-central x_revs_x0000_added_x0000_copies effb563bb7e5 c07a39dc4e80 : 0.132938 s, 0.127385 s, -0.005553 s, ? 0.9582 mozilla-central x000_revs_xx00_added_0_copies 6100d773079a 04a55431795e : 0.008683 s, 0.008740 s, +0.000057 s, ? 1.0066 mozilla-central x000_revs_x000_added_x_copies 9f17a6fc04f9 2d37b966abed : 0.005956 s, 0.005783 s, -0.000173 s, ? 0.9710 mozilla-central x000_revs_x000_added_x000_copies 7c97034feb78 4407bd0c6330 : 0.963905 s, 0.102184 s, -0.861721 s, ? 0.1060 mozilla-central x0000_revs_xx000_added_0_copies 9eec5917337d 67118cc6dcad : 0.049239 s, 0.046220 s, -0.003019 s, ? 0.9387 mozilla-central x0000_revs_xx000_added_x000_copies f78c615a656c 96a38b690156 : 4.217003 s, 0.315271 s, -3.901732 s, ? 0.0748 mozilla-central x00000_revs_x0000_added_x0000_copies 6832ae71433c 4c222a1d9a00 : killed , 3.478747 s mozilla-central x00000_revs_x00000_added_x000_copies 76caed42cf7c 1daa622bbe42 : killed , 4.766435 s mozilla-try x_revs_x_added_0_copies aaf6dde0deb8 9790f499805a : 0.001197 s, 0.001214 s, +0.000017 s, ? 1.0142 mozilla-try x_revs_x000_added_0_copies d8d0222927b4 5bb8ce8c7450 : 0.001213 s, 0.001221 s, +0.000008 s, ? 1.0066 mozilla-try x_revs_x_added_x_copies 092fcca11bdb 936255a0384a : 0.000762 s, 0.000613 s, -0.000149 s, ? 0.8045 mozilla-try x_revs_x00_added_x_copies b53d2fadbdb5 017afae788ec : 0.001909 s, 0.001904 s, -0.000005 s, ? 0.9974 mozilla-try x_revs_x000_added_x000_copies 20408ad61ce5 6f0ee96e21ad : 0.093021 s, 0.093000 s, -0.000021 s, ? 0.9998 mozilla-try x_revs_x0000_added_x0000_copies effb563bb7e5 c07a39dc4e80 : 0.134536 s, 0.132194 s, -0.002342 s, ? 0.9826 mozilla-try x000_revs_xx00_added_0_copies 6100d773079a 04a55431795e : 0.009071 s, 0.009069 s, -0.000002 s, ? 0.9998 mozilla-try x000_revs_x000_added_x_copies 9f17a6fc04f9 2d37b966abed : 0.006206 s, 0.006169 s, -0.000037 s, ? 0.9940 mozilla-try x000_revs_x000_added_x000_copies 1346fd0130e4 4c65cbdabc1f : 1.150502 s, 0.115540 s, -1.034962 s, ? 0.1004 mozilla-try x0000_revs_x_added_0_copies 63519bfd42ee a36a2a865d92 : 1.114864 s, 0.435381 s, -0.679483 s, ? 0.3905 mozilla-try x0000_revs_x_added_x_copies 9fe69ff0762d bcabf2a78927 : 1.042658 s, 0.415461 s, -0.627197 s, ? 0.3985 mozilla-try x0000_revs_xx000_added_x_copies 156f6e2674f2 4d0f2c178e66 : 0.447402 s, 0.155946 s, -0.291456 s, ? 0.3486 mozilla-try x0000_revs_xx000_added_0_copies 9eec5917337d 67118cc6dcad : 0.051132 s, 0.048521 s, -0.002611 s, ? 0.9489 mozilla-try x0000_revs_xx000_added_x000_copies 89294cd501d9 7ccb2fc7ccb5 : 83.508590 s, 9.843481 s, -73.665109 s, ? 0.1179 mozilla-try x0000_revs_x0000_added_x0000_copies e928c65095ed e951f4ad123a : 55.079813 s, 1.465128 s, -53.614685 s, ? 0.0266 mozilla-try x00000_revs_x00000_added_0_copies dc8a3ca7010e d16fde900c9c : 1.442793 s, 1.374283 s, -0.068510 s, ? 0.9525 mozilla-try x00000_revs_x0000_added_x0000_copies 8d3fafa80d4b eb884023b810 : killed , 5.255158 s Repo Cases Source-Rev Dest-Rev Py-time Rust-time Difference Factor ------------------------------------------------------------------------------------------------------------------------------------ mercurial x_revs_x_added_0_copies ad6b123de1c7 39cfcef4f463 : 0.000044 s, 0.000049 s, +0.000005 s, ? 1.1136 mercurial x_revs_x_added_x_copies 2b1c78674230 0c1d10351869 : 0.000138 s, 0.000182 s, +0.000044 s, ? 1.3188 mercurial x000_revs_x000_added_x_copies 81f8ff2a9bf2 dd3267698d84 : 0.005052 s, 0.005872 s, +0.000820 s, ? 1.1623 pypy x_revs_x_added_0_copies aed021ee8ae8 099ed31b181b : 0.000219 s, 0.000229 s, +0.000010 s, ? 1.0457 pypy x_revs_x000_added_0_copies 4aa4e1f8e19a 359343b9ac0e : 0.000055 s, 0.000058 s, +0.000003 s, ? 1.0545 pypy x_revs_x_added_x_copies ac52eb7bbbb0 72e022663155 : 0.000128 s, 0.000148 s, +0.000020 s, ? 1.1562 pypy x_revs_x00_added_x_copies c3b14617fbd7 ace7255d9a26 : 0.001089 s, 0.001205 s, +0.000116 s, ? 1.1065 pypy x_revs_x000_added_x000_copies df6f7a526b60 a83dc6a2d56f : 0.017407 s, 0.025662 s, +0.008255 s, ? 1.4742 pypy x000_revs_xx00_added_0_copies 89a76aede314 2f22446ff07e : 0.094175 s, 0.080113 s, -0.014062 s, ? 0.8507 pypy x000_revs_x000_added_x_copies 8a3b5bfd266e 2c68e87c3efe : 0.238009 s, 0.153030 s, -0.084979 s, ? 0.6430 pypy x000_revs_x000_added_x000_copies 89a76aede314 7b3dda341c84 : 0.125876 s, 0.098774 s, -0.027102 s, ? 0.7847 pypy x0000_revs_x_added_0_copies d1defd0dc478 c9cb1334cc78 : 3.581556 s, 2.780174 s, -0.801382 s, ? 0.7762 pypy x0000_revs_xx000_added_0_copies bf2c629d0071 4ffed77c095c : 0.016721 s, 0.022218 s, +0.005497 s, ? 1.3287 pypy x0000_revs_xx000_added_x000_copies 08ea3258278e d9fa043f30c0 : 0.242367 s, 0.252125 s, +0.009758 s, ? 1.0403 netbeans x_revs_x_added_0_copies fb0955ffcbcd a01e9239f9e7 : 0.000165 s, 0.000186 s, +0.000021 s, ? 1.1273 netbeans x_revs_x000_added_0_copies 6f360122949f 20eb231cc7d0 : 0.000114 s, 0.000133 s, +0.000019 s, ? 1.1667 netbeans x_revs_x_added_x_copies 1ada3faf6fb6 5a39d12eecf4 : 0.000296 s, 0.000320 s, +0.000024 s, ? 1.0811 netbeans x_revs_x00_added_x_copies 35be93ba1e2c 9eec5e90c05f : 0.001124 s, 0.001336 s, +0.000212 s, ? 1.1886 netbeans x000_revs_xx00_added_0_copies eac3045b4fdd 51d4ae7f1290 : 0.013060 s, 0.015573 s, +0.002513 s, ? 1.1924 netbeans x000_revs_x000_added_x_copies e2063d266acd 6081d72689dc : 0.017112 s, 0.018667 s, +0.001555 s, ? 1.0909 netbeans x000_revs_x000_added_x000_copies ff453e9fee32 411350406ec2 : 0.660350 s, 0.112534 s, -0.547816 s, ? 0.1704 netbeans x0000_revs_xx000_added_x000_copies 588c2d1ced70 1aad62e59ddd : 10.032499 s, 1.231869 s, -8.800630 s, ? 0.1228 mozilla-central x_revs_x_added_0_copies 3697f962bb7b 7015fcdd43a2 : 0.000189 s, 0.000197 s, +0.000008 s, ? 1.0423 mozilla-central x_revs_x000_added_0_copies dd390860c6c9 40d0c5bed75d : 0.000462 s, 0.000637 s, +0.000175 s, ? 1.3788 mozilla-central x_revs_x_added_x_copies 8d198483ae3b 14207ffc2b2f : 0.000270 s, 0.000303 s, +0.000033 s, ? 1.1222 mozilla-central x_revs_x00_added_x_copies 98cbc58cc6bc 446a150332c3 : 0.001474 s, 0.001663 s, +0.000189 s, ? 1.1282 mozilla-central x_revs_x000_added_x000_copies 3c684b4b8f68 0a5e72d1b479 : 0.004806 s, 0.007008 s, +0.002202 s, ? 1.4582 mozilla-central x_revs_x0000_added_x0000_copies effb563bb7e5 c07a39dc4e80 : 0.085150 s, 0.127385 s, +0.042235 s, ? 1.4960 mozilla-central x000_revs_xx00_added_0_copies 6100d773079a 04a55431795e : 0.007064 s, 0.008740 s, +0.001676 s, ? 1.2373 mozilla-central x000_revs_x000_added_x_copies 9f17a6fc04f9 2d37b966abed : 0.004741 s, 0.005783 s, +0.001042 s, ? 1.2198 mozilla-central x000_revs_x000_added_x000_copies 7c97034feb78 4407bd0c6330 : 0.190133 s, 0.102184 s, -0.087949 s, ? 0.5374 mozilla-central x0000_revs_xx000_added_0_copies 9eec5917337d 67118cc6dcad : 0.035651 s, 0.046220 s, +0.010569 s, ? 1.2965 mozilla-central x0000_revs_xx000_added_x000_copies f78c615a656c 96a38b690156 : 0.440694 s, 0.315271 s, -0.125423 s, ? 0.7154 mozilla-central x00000_revs_x0000_added_x0000_copies 6832ae71433c 4c222a1d9a00 : 18.454163 s, 3.478747 s, -14.975416 s, ? 0.1885 mozilla-central x00000_revs_x00000_added_x000_copies 76caed42cf7c 1daa622bbe42 : 31.562719 s, 4.766435 s, -26.796284 s, ? 0.1510 mozilla-try x_revs_x_added_0_copies aaf6dde0deb8 9790f499805a : 0.001189 s, 0.001214 s, +0.000025 s, ? 1.0210 mozilla-try x_revs_x000_added_0_copies d8d0222927b4 5bb8ce8c7450 : 0.001204 s, 0.001221 s, +0.000017 s, ? 1.0141 mozilla-try x_revs_x_added_x_copies 092fcca11bdb 936255a0384a : 0.000586 s, 0.000613 s, +0.000027 s, ? 1.0461 mozilla-try x_revs_x00_added_x_copies b53d2fadbdb5 017afae788ec : 0.001845 s, 0.001904 s, +0.000059 s, ? 1.0320 mozilla-try x_revs_x000_added_x000_copies 20408ad61ce5 6f0ee96e21ad : 0.063822 s, 0.093000 s, +0.029178 s, ? 1.4572 mozilla-try x_revs_x0000_added_x0000_copies effb563bb7e5 c07a39dc4e80 : 0.088038 s, 0.132194 s, +0.044156 s, ? 1.5016 mozilla-try x000_revs_xx00_added_0_copies 6100d773079a 04a55431795e : 0.007389 s, 0.009069 s, +0.001680 s, ? 1.2274 mozilla-try x000_revs_x000_added_x_copies 9f17a6fc04f9 2d37b966abed : 0.004868 s, 0.006169 s, +0.001301 s, ? 1.2673 mozilla-try x000_revs_x000_added_x000_copies 1346fd0130e4 4c65cbdabc1f : 0.222450 s, 0.115540 s, -0.106910 s, ? 0.5194 mozilla-try x0000_revs_x_added_0_copies 63519bfd42ee a36a2a865d92 : 0.370675 s, 0.435381 s, +0.064706 s, ? 1.1746 mozilla-try x0000_revs_x_added_x_copies 9fe69ff0762d bcabf2a78927 : 0.358020 s, 0.415461 s, +0.057441 s, ? 1.1604 mozilla-try x0000_revs_xx000_added_x_copies 156f6e2674f2 4d0f2c178e66 : 0.145235 s, 0.155946 s, +0.010711 s, ? 1.0737 mozilla-try x0000_revs_xx000_added_0_copies 9eec5917337d 67118cc6dcad : 0.037606 s, 0.048521 s, +0.010915 s, ? 1.2902 mozilla-try x0000_revs_xx000_added_x000_copies 89294cd501d9 7ccb2fc7ccb5 : 7.382439 s, 9.843481 s, +2.461042 s, ? 1.3334 mozilla-try x0000_revs_x0000_added_x0000_copies e928c65095ed e951f4ad123a : 7.273506 s, 1.465128 s, -5.808378 s, ? 0.2014 mozilla-try x00000_revs_x00000_added_0_copies dc8a3ca7010e d16fde900c9c : 1.074593 s, 1.374283 s, +0.299690 s, ? 1.2789 mozilla-try x00000_revs_x0000_added_x0000_copies 8d3fafa80d4b eb884023b810 : 27.746195 s, 5.255158 s, -22.491037 s, ? 0.1894 Repo Case Source-Rev Dest-Rev filelog sidedata Difference Factor --------------------------------------------------------------------------------------------------------------------------------------- mercurial x_revs_x_added_0_copies ad6b123de1c7 39cfcef4f463 : 0.000906 s, 0.000049 s, -0.000857 s, ? 0.054084 mercurial x_revs_x_added_x_copies 2b1c78674230 0c1d10351869 : 0.001832 s, 0.000182 s, -0.001650 s, ? 0.099345 mercurial x000_revs_x000_added_x_copies 81f8ff2a9bf2 dd3267698d84 : 0.018101 s, 0.005872 s, -0.012229 s, ? 0.324402 pypy x_revs_x_added_0_copies aed021ee8ae8 099ed31b181b : 0.001508 s, 0.000229 s, -0.001279 s, ? 0.151857 pypy x_revs_x000_added_0_copies 4aa4e1f8e19a 359343b9ac0e : 0.207438 s, 0.000058 s, -0.207380 s, ? 0.000280 pypy x_revs_x_added_x_copies ac52eb7bbbb0 72e022663155 : 0.016956 s, 0.000148 s, -0.016808 s, ? 0.008728 pypy x_revs_x00_added_x_copies c3b14617fbd7 ace7255d9a26 : 0.019129 s, 0.001205 s, -0.017924 s, ? 0.062993 pypy x_revs_x000_added_x000_copies df6f7a526b60 a83dc6a2d56f : 0.772050 s, 0.025662 s, -0.746388 s, ? 0.033239 pypy x000_revs_xx00_added_0_copies 89a76aede314 2f22446ff07e : 1.181775 s, 0.080113 s, -1.101662 s, ? 0.067790 pypy x000_revs_x000_added_x_copies 8a3b5bfd266e 2c68e87c3efe : 1.255717 s, 0.153030 s, -1.102687 s, ? 0.121867 pypy x000_revs_x000_added_x000_copies 89a76aede314 7b3dda341c84 : 1.628132 s, 0.098774 s, -1.529358 s, ? 0.060667 pypy x0000_revs_x_added_0_copies d1defd0dc478 c9cb1334cc78 : 0.001055 s, 2.780174 s, +2.779119 s, ? 2635.236019 pypy x0000_revs_xx000_added_0_copies bf2c629d0071 4ffed77c095c : 1.056756 s, 0.022218 s, -1.034538 s, ? 0.021025 pypy x0000_revs_xx000_added_x000_copies 08ea3258278e d9fa043f30c0 : 1.354211 s, 0.252125 s, -1.102086 s, ? 0.186179 netbeans x_revs_x_added_0_copies fb0955ffcbcd a01e9239f9e7 : 0.027759 s, 0.000186 s, -0.027573 s, ? 0.006701 netbeans x_revs_x000_added_0_copies 6f360122949f 20eb231cc7d0 : 0.133382 s, 0.000133 s, -0.133249 s, ? 0.000997 netbeans x_revs_x_added_x_copies 1ada3faf6fb6 5a39d12eecf4 : 0.025353 s, 0.000320 s, -0.025033 s, ? 0.012622 netbeans x_revs_x00_added_x_copies 35be93ba1e2c 9eec5e90c05f : 0.052939 s, 0.001336 s, -0.051603 s, ? 0.025237 netbeans x000_revs_xx00_added_0_copies eac3045b4fdd 51d4ae7f1290 : 0.037532 s, 0.015573 s, -0.021959 s, ? 0.414926 netbeans x000_revs_x000_added_x_copies e2063d266acd 6081d72689dc : 0.195401 s, 0.018667 s, -0.176734 s, ? 0.095532 netbeans x000_revs_x000_added_x000_copies ff453e9fee32 411350406ec2 : 0.939593 s, 0.112534 s, -0.827059 s, ? 0.119769 netbeans x0000_revs_xx000_added_x000_copies 588c2d1ced70 1aad62e59ddd : 3.824967 s, 1.231869 s, -2.593098 s, ? 0.322060 mozilla-central x_revs_x_added_0_copies 3697f962bb7b 7015fcdd43a2 : 0.024626 s, 0.000197 s, -0.024429 s, ? 0.008000 mozilla-central x_revs_x000_added_0_copies dd390860c6c9 40d0c5bed75d : 0.141098 s, 0.000637 s, -0.140461 s, ? 0.004515 mozilla-central x_revs_x_added_x_copies 8d198483ae3b 14207ffc2b2f : 0.025973 s, 0.000303 s, -0.025670 s, ? 0.011666 mozilla-central x_revs_x00_added_x_copies 98cbc58cc6bc 446a150332c3 : 0.085098 s, 0.001663 s, -0.083435 s, ? 0.019542 mozilla-central x_revs_x000_added_x000_copies 3c684b4b8f68 0a5e72d1b479 : 0.196623 s, 0.007008 s, -0.189615 s, ? 0.035642 mozilla-central x_revs_x0000_added_x0000_copies effb563bb7e5 c07a39dc4e80 : 2.182911 s, 0.127385 s, -2.055526 s, ? 0.058356 mozilla-central x000_revs_xx00_added_0_copies 6100d773079a 04a55431795e : 0.088865 s, 0.008740 s, -0.080125 s, ? 0.098351 mozilla-central x000_revs_x000_added_x_copies 9f17a6fc04f9 2d37b966abed : 0.731211 s, 0.005783 s, -0.725428 s, ? 0.007909 mozilla-central x000_revs_x000_added_x000_copies 7c97034feb78 4407bd0c6330 : 1.142414 s, 0.102184 s, -1.040230 s, ? 0.089446 mozilla-central x0000_revs_xx000_added_0_copies 9eec5917337d 67118cc6dcad : 6.667504 s, 0.046220 s, -6.621284 s, ? 0.006932 mozilla-central x0000_revs_xx000_added_x000_copies f78c615a656c 96a38b690156 : 3.267274 s, 0.315271 s, -2.952003 s, ? 0.096494 mozilla-central x00000_revs_x0000_added_x0000_copies 6832ae71433c 4c222a1d9a00 : 16.038104 s, 3.478747 s, -12.559357 s, ? 0.216905 mozilla-central x00000_revs_x00000_added_x000_copies 76caed42cf7c 1daa622bbe42 : 20.639928 s, 4.766435 s, -15.873493 s, ? 0.230933 mozilla-try x_revs_x_added_0_copies aaf6dde0deb8 9790f499805a : 0.080513 s, 0.001214 s, -0.079299 s, ? 0.015078 mozilla-try x_revs_x000_added_0_copies d8d0222927b4 5bb8ce8c7450 : 0.502965 s, 0.001221 s, -0.501744 s, ? 0.002428 mozilla-try x_revs_x_added_x_copies 092fcca11bdb 936255a0384a : 0.021408 s, 0.000613 s, -0.020795 s, ? 0.028634 mozilla-try x_revs_x00_added_x_copies b53d2fadbdb5 017afae788ec : 0.228498 s, 0.001904 s, -0.226594 s, ? 0.008333 mozilla-try x_revs_x000_added_x000_copies 20408ad61ce5 6f0ee96e21ad : 1.118490 s, 0.093000 s, -1.025490 s, ? 0.083148 mozilla-try x_revs_x0000_added_x0000_copies effb563bb7e5 c07a39dc4e80 : 2.188390 s, 0.132194 s, -2.056196 s, ? 0.060407 mozilla-try x000_revs_xx00_added_0_copies 6100d773079a 04a55431795e : 0.089755 s, 0.009069 s, -0.080686 s, ? 0.101042 mozilla-try x000_revs_x000_added_x_copies 9f17a6fc04f9 2d37b966abed : 0.750223 s, 0.006169 s, -0.744054 s, ? 0.008223 mozilla-try x000_revs_x000_added_x000_copies 1346fd0130e4 4c65cbdabc1f : 1.189708 s, 0.115540 s, -1.074168 s, ? 0.097116 mozilla-try x0000_revs_x_added_0_copies 63519bfd42ee a36a2a865d92 : 0.088715 s, 0.435381 s, +0.346666 s, ? 4.907637 mozilla-try x0000_revs_x_added_x_copies 9fe69ff0762d bcabf2a78927 : 0.080765 s, 0.415461 s, +0.334696 s, ? 5.144072 mozilla-try x0000_revs_xx000_added_x_copies 156f6e2674f2 4d0f2c178e66 : 7.487310 s, 0.155946 s, -7.331364 s, ? 0.020828 mozilla-try x0000_revs_xx000_added_0_copies 9eec5917337d 67118cc6dcad : 6.676682 s, 0.048521 s, -6.628161 s, ? 0.007267 mozilla-try x0000_revs_xx000_added_x000_copies 89294cd501d9 7ccb2fc7ccb5 : 7.598509 s, 9.843481 s, +2.244972 s, ? 1.295449 mozilla-try x0000_revs_x0000_added_x0000_copies e928c65095ed e951f4ad123a : 9.871850 s, 1.465128 s, -8.406722 s, ? 0.148415 mozilla-try x00000_revs_x_added_0_copies 6a320851d377 1ebb79acd503 : 0.092232 s, killed mozilla-try x00000_revs_x00000_added_0_copies dc8a3ca7010e d16fde900c9c : 26.471560 s, 1.374283 s, -25.097277 s, ? 0.051915 mozilla-try x00000_revs_x_added_x_copies 5173c4b6f97c 95d83ee7242d : 0.093892 s, killed mozilla-try x00000_revs_x000_added_x_copies 9126823d0e9c ca82787bb23c : 0.227503 s, killed mozilla-try x00000_revs_x0000_added_x0000_copies 8d3fafa80d4b eb884023b810 : 19.064699 s, 5.255158 s, -13.809541 s, ? 0.275649 mozilla-try x00000_revs_x00000_added_x0000_copies 1b661134e2ca 1ae03d022d6d : 21.145391 s, killed mozilla-try x00000_revs_x00000_added_x000_copies 9b2a99adc05e 8e29777b48e6 : 25.304164 s, killed Differential Revision: https://phab.mercurial-scm.org/D9302
author Pierre-Yves David <pierre-yves.david@octobus.net>
date Tue, 21 Apr 2020 15:00:32 +0200
parents b0d6309ff50c
children 88e741bf2d93
Ignore whitespace changes - Everywhere: Within whitespace: At end of lines:
rev   line source
44228
7f86426fdd2c rust-node: binary Node ID and conversion utilities
Georges Racinet <georges.racinet@octobus.net>
parents:
diff changeset
1 // Copyright 2019-2020 Georges Racinet <georges.racinet@octobus.net>
7f86426fdd2c rust-node: binary Node ID and conversion utilities
Georges Racinet <georges.racinet@octobus.net>
parents:
diff changeset
2 //
7f86426fdd2c rust-node: binary Node ID and conversion utilities
Georges Racinet <georges.racinet@octobus.net>
parents:
diff changeset
3 // This software may be used and distributed according to the terms of the
7f86426fdd2c rust-node: binary Node ID and conversion utilities
Georges Racinet <georges.racinet@octobus.net>
parents:
diff changeset
4 // GNU General Public License version 2 or any later version.
7f86426fdd2c rust-node: binary Node ID and conversion utilities
Georges Racinet <georges.racinet@octobus.net>
parents:
diff changeset
5
7f86426fdd2c rust-node: binary Node ID and conversion utilities
Georges Racinet <georges.racinet@octobus.net>
parents:
diff changeset
6 //! Definitions and utilities for Revision nodes
7f86426fdd2c rust-node: binary Node ID and conversion utilities
Georges Racinet <georges.racinet@octobus.net>
parents:
diff changeset
7 //!
7f86426fdd2c rust-node: binary Node ID and conversion utilities
Georges Racinet <georges.racinet@octobus.net>
parents:
diff changeset
8 //! In Mercurial code base, it is customary to call "a node" the binary SHA
7f86426fdd2c rust-node: binary Node ID and conversion utilities
Georges Racinet <georges.racinet@octobus.net>
parents:
diff changeset
9 //! of a revision.
7f86426fdd2c rust-node: binary Node ID and conversion utilities
Georges Racinet <georges.racinet@octobus.net>
parents:
diff changeset
10
7f86426fdd2c rust-node: binary Node ID and conversion utilities
Georges Racinet <georges.racinet@octobus.net>
parents:
diff changeset
11 use hex::{self, FromHex, FromHexError};
7f86426fdd2c rust-node: binary Node ID and conversion utilities
Georges Racinet <georges.racinet@octobus.net>
parents:
diff changeset
12
7f86426fdd2c rust-node: binary Node ID and conversion utilities
Georges Racinet <georges.racinet@octobus.net>
parents:
diff changeset
13 /// The length in bytes of a `Node`
7f86426fdd2c rust-node: binary Node ID and conversion utilities
Georges Racinet <georges.racinet@octobus.net>
parents:
diff changeset
14 ///
7f86426fdd2c rust-node: binary Node ID and conversion utilities
Georges Racinet <georges.racinet@octobus.net>
parents:
diff changeset
15 /// This constant is meant to ease refactors of this module, and
7f86426fdd2c rust-node: binary Node ID and conversion utilities
Georges Racinet <georges.racinet@octobus.net>
parents:
diff changeset
16 /// are private so that calling code does not expect all nodes have
7f86426fdd2c rust-node: binary Node ID and conversion utilities
Georges Racinet <georges.racinet@octobus.net>
parents:
diff changeset
17 /// the same size, should we support several formats concurrently in
7f86426fdd2c rust-node: binary Node ID and conversion utilities
Georges Racinet <georges.racinet@octobus.net>
parents:
diff changeset
18 /// the future.
45537
b0d6309ff50c hg-core: check data integrity in `Revlog`
Antoine Cezar <antoine.cezar@octobus.net>
parents: 44998
diff changeset
19 pub const NODE_BYTES_LENGTH: usize = 20;
b0d6309ff50c hg-core: check data integrity in `Revlog`
Antoine Cezar <antoine.cezar@octobus.net>
parents: 44998
diff changeset
20
b0d6309ff50c hg-core: check data integrity in `Revlog`
Antoine Cezar <antoine.cezar@octobus.net>
parents: 44998
diff changeset
21 /// Id of the null node.
b0d6309ff50c hg-core: check data integrity in `Revlog`
Antoine Cezar <antoine.cezar@octobus.net>
parents: 44998
diff changeset
22 ///
b0d6309ff50c hg-core: check data integrity in `Revlog`
Antoine Cezar <antoine.cezar@octobus.net>
parents: 44998
diff changeset
23 /// Used to indicate the absence of node.
b0d6309ff50c hg-core: check data integrity in `Revlog`
Antoine Cezar <antoine.cezar@octobus.net>
parents: 44998
diff changeset
24 pub const NULL_NODE_ID: [u8; NODE_BYTES_LENGTH] = [0u8; NODE_BYTES_LENGTH];
44228
7f86426fdd2c rust-node: binary Node ID and conversion utilities
Georges Racinet <georges.racinet@octobus.net>
parents:
diff changeset
25
7f86426fdd2c rust-node: binary Node ID and conversion utilities
Georges Racinet <georges.racinet@octobus.net>
parents:
diff changeset
26 /// The length in bytes of a `Node`
7f86426fdd2c rust-node: binary Node ID and conversion utilities
Georges Racinet <georges.racinet@octobus.net>
parents:
diff changeset
27 ///
7f86426fdd2c rust-node: binary Node ID and conversion utilities
Georges Racinet <georges.racinet@octobus.net>
parents:
diff changeset
28 /// see also `NODES_BYTES_LENGTH` about it being private.
7f86426fdd2c rust-node: binary Node ID and conversion utilities
Georges Racinet <georges.racinet@octobus.net>
parents:
diff changeset
29 const NODE_NYBBLES_LENGTH: usize = 2 * NODE_BYTES_LENGTH;
7f86426fdd2c rust-node: binary Node ID and conversion utilities
Georges Racinet <georges.racinet@octobus.net>
parents:
diff changeset
30
7f86426fdd2c rust-node: binary Node ID and conversion utilities
Georges Racinet <georges.racinet@octobus.net>
parents:
diff changeset
31 /// Private alias for readability and to ease future change
7f86426fdd2c rust-node: binary Node ID and conversion utilities
Georges Racinet <georges.racinet@octobus.net>
parents:
diff changeset
32 type NodeData = [u8; NODE_BYTES_LENGTH];
7f86426fdd2c rust-node: binary Node ID and conversion utilities
Georges Racinet <georges.racinet@octobus.net>
parents:
diff changeset
33
7f86426fdd2c rust-node: binary Node ID and conversion utilities
Georges Racinet <georges.racinet@octobus.net>
parents:
diff changeset
34 /// Binary revision SHA
7f86426fdd2c rust-node: binary Node ID and conversion utilities
Georges Racinet <georges.racinet@octobus.net>
parents:
diff changeset
35 ///
7f86426fdd2c rust-node: binary Node ID and conversion utilities
Georges Racinet <georges.racinet@octobus.net>
parents:
diff changeset
36 /// ## Future changes of hash size
7f86426fdd2c rust-node: binary Node ID and conversion utilities
Georges Racinet <georges.racinet@octobus.net>
parents:
diff changeset
37 ///
7f86426fdd2c rust-node: binary Node ID and conversion utilities
Georges Racinet <georges.racinet@octobus.net>
parents:
diff changeset
38 /// To accomodate future changes of hash size, Rust callers
7f86426fdd2c rust-node: binary Node ID and conversion utilities
Georges Racinet <georges.racinet@octobus.net>
parents:
diff changeset
39 /// should use the conversion methods at the boundaries (FFI, actual
7f86426fdd2c rust-node: binary Node ID and conversion utilities
Georges Racinet <georges.racinet@octobus.net>
parents:
diff changeset
40 /// computation of hashes and I/O) only, and only if required.
7f86426fdd2c rust-node: binary Node ID and conversion utilities
Georges Racinet <georges.racinet@octobus.net>
parents:
diff changeset
41 ///
7f86426fdd2c rust-node: binary Node ID and conversion utilities
Georges Racinet <georges.racinet@octobus.net>
parents:
diff changeset
42 /// All other callers outside of unit tests should just handle `Node` values
7f86426fdd2c rust-node: binary Node ID and conversion utilities
Georges Racinet <georges.racinet@octobus.net>
parents:
diff changeset
43 /// and never make any assumption on the actual length, using [`nybbles_len`]
7f86426fdd2c rust-node: binary Node ID and conversion utilities
Georges Racinet <georges.racinet@octobus.net>
parents:
diff changeset
44 /// if they need a loop boundary.
7f86426fdd2c rust-node: binary Node ID and conversion utilities
Georges Racinet <georges.racinet@octobus.net>
parents:
diff changeset
45 ///
7f86426fdd2c rust-node: binary Node ID and conversion utilities
Georges Racinet <georges.racinet@octobus.net>
parents:
diff changeset
46 /// All methods that create a `Node` either take a type that enforces
7f86426fdd2c rust-node: binary Node ID and conversion utilities
Georges Racinet <georges.racinet@octobus.net>
parents:
diff changeset
47 /// the size or fail immediately at runtime with [`ExactLengthRequired`].
7f86426fdd2c rust-node: binary Node ID and conversion utilities
Georges Racinet <georges.racinet@octobus.net>
parents:
diff changeset
48 ///
7f86426fdd2c rust-node: binary Node ID and conversion utilities
Georges Racinet <georges.racinet@octobus.net>
parents:
diff changeset
49 /// [`nybbles_len`]: #method.nybbles_len
7f86426fdd2c rust-node: binary Node ID and conversion utilities
Georges Racinet <georges.racinet@octobus.net>
parents:
diff changeset
50 /// [`ExactLengthRequired`]: struct.NodeError#variant.ExactLengthRequired
7f86426fdd2c rust-node: binary Node ID and conversion utilities
Georges Racinet <georges.racinet@octobus.net>
parents:
diff changeset
51 #[derive(Clone, Debug, PartialEq)]
44512
166349510398 revlog: using two new functions in C capsule from Rust code
Georges Racinet <georges.racinet@octobus.net>
parents: 44419
diff changeset
52 #[repr(transparent)]
44228
7f86426fdd2c rust-node: binary Node ID and conversion utilities
Georges Racinet <georges.racinet@octobus.net>
parents:
diff changeset
53 pub struct Node {
7f86426fdd2c rust-node: binary Node ID and conversion utilities
Georges Racinet <georges.racinet@octobus.net>
parents:
diff changeset
54 data: NodeData,
7f86426fdd2c rust-node: binary Node ID and conversion utilities
Georges Racinet <georges.racinet@octobus.net>
parents:
diff changeset
55 }
7f86426fdd2c rust-node: binary Node ID and conversion utilities
Georges Racinet <georges.racinet@octobus.net>
parents:
diff changeset
56
7f86426fdd2c rust-node: binary Node ID and conversion utilities
Georges Racinet <georges.racinet@octobus.net>
parents:
diff changeset
57 /// The node value for NULL_REVISION
7f86426fdd2c rust-node: binary Node ID and conversion utilities
Georges Racinet <georges.racinet@octobus.net>
parents:
diff changeset
58 pub const NULL_NODE: Node = Node {
7f86426fdd2c rust-node: binary Node ID and conversion utilities
Georges Racinet <georges.racinet@octobus.net>
parents:
diff changeset
59 data: [0; NODE_BYTES_LENGTH],
7f86426fdd2c rust-node: binary Node ID and conversion utilities
Georges Racinet <georges.racinet@octobus.net>
parents:
diff changeset
60 };
7f86426fdd2c rust-node: binary Node ID and conversion utilities
Georges Racinet <georges.racinet@octobus.net>
parents:
diff changeset
61
7f86426fdd2c rust-node: binary Node ID and conversion utilities
Georges Racinet <georges.racinet@octobus.net>
parents:
diff changeset
62 impl From<NodeData> for Node {
7f86426fdd2c rust-node: binary Node ID and conversion utilities
Georges Racinet <georges.racinet@octobus.net>
parents:
diff changeset
63 fn from(data: NodeData) -> Node {
7f86426fdd2c rust-node: binary Node ID and conversion utilities
Georges Racinet <georges.racinet@octobus.net>
parents:
diff changeset
64 Node { data }
7f86426fdd2c rust-node: binary Node ID and conversion utilities
Georges Racinet <georges.racinet@octobus.net>
parents:
diff changeset
65 }
7f86426fdd2c rust-node: binary Node ID and conversion utilities
Georges Racinet <georges.racinet@octobus.net>
parents:
diff changeset
66 }
7f86426fdd2c rust-node: binary Node ID and conversion utilities
Georges Racinet <georges.racinet@octobus.net>
parents:
diff changeset
67
7f86426fdd2c rust-node: binary Node ID and conversion utilities
Georges Racinet <georges.racinet@octobus.net>
parents:
diff changeset
68 #[derive(Debug, PartialEq)]
7f86426fdd2c rust-node: binary Node ID and conversion utilities
Georges Racinet <georges.racinet@octobus.net>
parents:
diff changeset
69 pub enum NodeError {
7f86426fdd2c rust-node: binary Node ID and conversion utilities
Georges Racinet <georges.racinet@octobus.net>
parents:
diff changeset
70 ExactLengthRequired(usize, String),
44257
9896a8d0d3d2 rust-node: handling binary Node prefix
Georges Racinet <georges.racinet@octobus.net>
parents: 44228
diff changeset
71 PrefixTooLong(String),
44228
7f86426fdd2c rust-node: binary Node ID and conversion utilities
Georges Racinet <georges.racinet@octobus.net>
parents:
diff changeset
72 HexError(FromHexError, String),
7f86426fdd2c rust-node: binary Node ID and conversion utilities
Georges Racinet <georges.racinet@octobus.net>
parents:
diff changeset
73 }
7f86426fdd2c rust-node: binary Node ID and conversion utilities
Georges Racinet <georges.racinet@octobus.net>
parents:
diff changeset
74
7f86426fdd2c rust-node: binary Node ID and conversion utilities
Georges Racinet <georges.racinet@octobus.net>
parents:
diff changeset
75 /// Low level utility function, also for prefixes
7f86426fdd2c rust-node: binary Node ID and conversion utilities
Georges Racinet <georges.racinet@octobus.net>
parents:
diff changeset
76 fn get_nybble(s: &[u8], i: usize) -> u8 {
7f86426fdd2c rust-node: binary Node ID and conversion utilities
Georges Racinet <georges.racinet@octobus.net>
parents:
diff changeset
77 if i % 2 == 0 {
7f86426fdd2c rust-node: binary Node ID and conversion utilities
Georges Racinet <georges.racinet@octobus.net>
parents:
diff changeset
78 s[i / 2] >> 4
7f86426fdd2c rust-node: binary Node ID and conversion utilities
Georges Racinet <georges.racinet@octobus.net>
parents:
diff changeset
79 } else {
7f86426fdd2c rust-node: binary Node ID and conversion utilities
Georges Racinet <georges.racinet@octobus.net>
parents:
diff changeset
80 s[i / 2] & 0x0f
7f86426fdd2c rust-node: binary Node ID and conversion utilities
Georges Racinet <georges.racinet@octobus.net>
parents:
diff changeset
81 }
7f86426fdd2c rust-node: binary Node ID and conversion utilities
Georges Racinet <georges.racinet@octobus.net>
parents:
diff changeset
82 }
7f86426fdd2c rust-node: binary Node ID and conversion utilities
Georges Racinet <georges.racinet@octobus.net>
parents:
diff changeset
83
7f86426fdd2c rust-node: binary Node ID and conversion utilities
Georges Racinet <georges.racinet@octobus.net>
parents:
diff changeset
84 impl Node {
7f86426fdd2c rust-node: binary Node ID and conversion utilities
Georges Racinet <georges.racinet@octobus.net>
parents:
diff changeset
85 /// Retrieve the `i`th half-byte of the binary data.
7f86426fdd2c rust-node: binary Node ID and conversion utilities
Georges Racinet <georges.racinet@octobus.net>
parents:
diff changeset
86 ///
7f86426fdd2c rust-node: binary Node ID and conversion utilities
Georges Racinet <georges.racinet@octobus.net>
parents:
diff changeset
87 /// This is also the `i`th hexadecimal digit in numeric form,
7f86426fdd2c rust-node: binary Node ID and conversion utilities
Georges Racinet <georges.racinet@octobus.net>
parents:
diff changeset
88 /// also called a [nybble](https://en.wikipedia.org/wiki/Nibble).
7f86426fdd2c rust-node: binary Node ID and conversion utilities
Georges Racinet <georges.racinet@octobus.net>
parents:
diff changeset
89 pub fn get_nybble(&self, i: usize) -> u8 {
7f86426fdd2c rust-node: binary Node ID and conversion utilities
Georges Racinet <georges.racinet@octobus.net>
parents:
diff changeset
90 get_nybble(&self.data, i)
7f86426fdd2c rust-node: binary Node ID and conversion utilities
Georges Racinet <georges.racinet@octobus.net>
parents:
diff changeset
91 }
7f86426fdd2c rust-node: binary Node ID and conversion utilities
Georges Racinet <georges.racinet@octobus.net>
parents:
diff changeset
92
7f86426fdd2c rust-node: binary Node ID and conversion utilities
Georges Racinet <georges.racinet@octobus.net>
parents:
diff changeset
93 /// Length of the data, in nybbles
7f86426fdd2c rust-node: binary Node ID and conversion utilities
Georges Racinet <georges.racinet@octobus.net>
parents:
diff changeset
94 pub fn nybbles_len(&self) -> usize {
7f86426fdd2c rust-node: binary Node ID and conversion utilities
Georges Racinet <georges.racinet@octobus.net>
parents:
diff changeset
95 // public exposure as an instance method only, so that we can
7f86426fdd2c rust-node: binary Node ID and conversion utilities
Georges Racinet <georges.racinet@octobus.net>
parents:
diff changeset
96 // easily support several sizes of hashes if needed in the future.
7f86426fdd2c rust-node: binary Node ID and conversion utilities
Georges Racinet <georges.racinet@octobus.net>
parents:
diff changeset
97 NODE_NYBBLES_LENGTH
7f86426fdd2c rust-node: binary Node ID and conversion utilities
Georges Racinet <georges.racinet@octobus.net>
parents:
diff changeset
98 }
7f86426fdd2c rust-node: binary Node ID and conversion utilities
Georges Racinet <georges.racinet@octobus.net>
parents:
diff changeset
99
7f86426fdd2c rust-node: binary Node ID and conversion utilities
Georges Racinet <georges.racinet@octobus.net>
parents:
diff changeset
100 /// Convert from hexadecimal string representation
7f86426fdd2c rust-node: binary Node ID and conversion utilities
Georges Racinet <georges.racinet@octobus.net>
parents:
diff changeset
101 ///
7f86426fdd2c rust-node: binary Node ID and conversion utilities
Georges Racinet <georges.racinet@octobus.net>
parents:
diff changeset
102 /// Exact length is required.
7f86426fdd2c rust-node: binary Node ID and conversion utilities
Georges Racinet <georges.racinet@octobus.net>
parents:
diff changeset
103 ///
7f86426fdd2c rust-node: binary Node ID and conversion utilities
Georges Racinet <georges.racinet@octobus.net>
parents:
diff changeset
104 /// To be used in FFI and I/O only, in order to facilitate future
7f86426fdd2c rust-node: binary Node ID and conversion utilities
Georges Racinet <georges.racinet@octobus.net>
parents:
diff changeset
105 /// changes of hash format.
7f86426fdd2c rust-node: binary Node ID and conversion utilities
Georges Racinet <georges.racinet@octobus.net>
parents:
diff changeset
106 pub fn from_hex(hex: &str) -> Result<Node, NodeError> {
7f86426fdd2c rust-node: binary Node ID and conversion utilities
Georges Racinet <georges.racinet@octobus.net>
parents:
diff changeset
107 Ok(NodeData::from_hex(hex)
7f86426fdd2c rust-node: binary Node ID and conversion utilities
Georges Racinet <georges.racinet@octobus.net>
parents:
diff changeset
108 .map_err(|e| NodeError::from((e, hex)))?
7f86426fdd2c rust-node: binary Node ID and conversion utilities
Georges Racinet <georges.racinet@octobus.net>
parents:
diff changeset
109 .into())
7f86426fdd2c rust-node: binary Node ID and conversion utilities
Georges Racinet <georges.racinet@octobus.net>
parents:
diff changeset
110 }
7f86426fdd2c rust-node: binary Node ID and conversion utilities
Georges Racinet <georges.racinet@octobus.net>
parents:
diff changeset
111
7f86426fdd2c rust-node: binary Node ID and conversion utilities
Georges Racinet <georges.racinet@octobus.net>
parents:
diff changeset
112 /// Convert to hexadecimal string representation
7f86426fdd2c rust-node: binary Node ID and conversion utilities
Georges Racinet <georges.racinet@octobus.net>
parents:
diff changeset
113 ///
7f86426fdd2c rust-node: binary Node ID and conversion utilities
Georges Racinet <georges.racinet@octobus.net>
parents:
diff changeset
114 /// To be used in FFI and I/O only, in order to facilitate future
7f86426fdd2c rust-node: binary Node ID and conversion utilities
Georges Racinet <georges.racinet@octobus.net>
parents:
diff changeset
115 /// changes of hash format.
7f86426fdd2c rust-node: binary Node ID and conversion utilities
Georges Racinet <georges.racinet@octobus.net>
parents:
diff changeset
116 pub fn encode_hex(&self) -> String {
7f86426fdd2c rust-node: binary Node ID and conversion utilities
Georges Racinet <georges.racinet@octobus.net>
parents:
diff changeset
117 hex::encode(self.data)
7f86426fdd2c rust-node: binary Node ID and conversion utilities
Georges Racinet <georges.racinet@octobus.net>
parents:
diff changeset
118 }
7f86426fdd2c rust-node: binary Node ID and conversion utilities
Georges Racinet <georges.racinet@octobus.net>
parents:
diff changeset
119
7f86426fdd2c rust-node: binary Node ID and conversion utilities
Georges Racinet <georges.racinet@octobus.net>
parents:
diff changeset
120 /// Provide access to binary data
7f86426fdd2c rust-node: binary Node ID and conversion utilities
Georges Racinet <georges.racinet@octobus.net>
parents:
diff changeset
121 ///
7f86426fdd2c rust-node: binary Node ID and conversion utilities
Georges Racinet <georges.racinet@octobus.net>
parents:
diff changeset
122 /// This is needed by FFI layers, for instance to return expected
7f86426fdd2c rust-node: binary Node ID and conversion utilities
Georges Racinet <georges.racinet@octobus.net>
parents:
diff changeset
123 /// binary values to Python.
7f86426fdd2c rust-node: binary Node ID and conversion utilities
Georges Racinet <georges.racinet@octobus.net>
parents:
diff changeset
124 pub fn as_bytes(&self) -> &[u8] {
7f86426fdd2c rust-node: binary Node ID and conversion utilities
Georges Racinet <georges.racinet@octobus.net>
parents:
diff changeset
125 &self.data
7f86426fdd2c rust-node: binary Node ID and conversion utilities
Georges Racinet <georges.racinet@octobus.net>
parents:
diff changeset
126 }
7f86426fdd2c rust-node: binary Node ID and conversion utilities
Georges Racinet <georges.racinet@octobus.net>
parents:
diff changeset
127 }
7f86426fdd2c rust-node: binary Node ID and conversion utilities
Georges Racinet <georges.racinet@octobus.net>
parents:
diff changeset
128
44257
9896a8d0d3d2 rust-node: handling binary Node prefix
Georges Racinet <georges.racinet@octobus.net>
parents: 44228
diff changeset
129 impl<T: AsRef<str>> From<(FromHexError, T)> for NodeError {
9896a8d0d3d2 rust-node: handling binary Node prefix
Georges Racinet <georges.racinet@octobus.net>
parents: 44228
diff changeset
130 fn from(err_offender: (FromHexError, T)) -> Self {
44228
7f86426fdd2c rust-node: binary Node ID and conversion utilities
Georges Racinet <georges.racinet@octobus.net>
parents:
diff changeset
131 let (err, offender) = err_offender;
7f86426fdd2c rust-node: binary Node ID and conversion utilities
Georges Racinet <georges.racinet@octobus.net>
parents:
diff changeset
132 match err {
7f86426fdd2c rust-node: binary Node ID and conversion utilities
Georges Racinet <georges.racinet@octobus.net>
parents:
diff changeset
133 FromHexError::InvalidStringLength => {
7f86426fdd2c rust-node: binary Node ID and conversion utilities
Georges Racinet <georges.racinet@octobus.net>
parents:
diff changeset
134 NodeError::ExactLengthRequired(
7f86426fdd2c rust-node: binary Node ID and conversion utilities
Georges Racinet <georges.racinet@octobus.net>
parents:
diff changeset
135 NODE_NYBBLES_LENGTH,
44257
9896a8d0d3d2 rust-node: handling binary Node prefix
Georges Racinet <georges.racinet@octobus.net>
parents: 44228
diff changeset
136 offender.as_ref().to_owned(),
44228
7f86426fdd2c rust-node: binary Node ID and conversion utilities
Georges Racinet <georges.racinet@octobus.net>
parents:
diff changeset
137 )
7f86426fdd2c rust-node: binary Node ID and conversion utilities
Georges Racinet <georges.racinet@octobus.net>
parents:
diff changeset
138 }
44257
9896a8d0d3d2 rust-node: handling binary Node prefix
Georges Racinet <georges.racinet@octobus.net>
parents: 44228
diff changeset
139 _ => NodeError::HexError(err, offender.as_ref().to_owned()),
9896a8d0d3d2 rust-node: handling binary Node prefix
Georges Racinet <georges.racinet@octobus.net>
parents: 44228
diff changeset
140 }
9896a8d0d3d2 rust-node: handling binary Node prefix
Georges Racinet <georges.racinet@octobus.net>
parents: 44228
diff changeset
141 }
9896a8d0d3d2 rust-node: handling binary Node prefix
Georges Racinet <georges.racinet@octobus.net>
parents: 44228
diff changeset
142 }
9896a8d0d3d2 rust-node: handling binary Node prefix
Georges Racinet <georges.racinet@octobus.net>
parents: 44228
diff changeset
143
9896a8d0d3d2 rust-node: handling binary Node prefix
Georges Racinet <georges.racinet@octobus.net>
parents: 44228
diff changeset
144 /// The beginning of a binary revision SHA.
9896a8d0d3d2 rust-node: handling binary Node prefix
Georges Racinet <georges.racinet@octobus.net>
parents: 44228
diff changeset
145 ///
9896a8d0d3d2 rust-node: handling binary Node prefix
Georges Racinet <georges.racinet@octobus.net>
parents: 44228
diff changeset
146 /// Since it can potentially come from an hexadecimal representation with
9896a8d0d3d2 rust-node: handling binary Node prefix
Georges Racinet <georges.racinet@octobus.net>
parents: 44228
diff changeset
147 /// odd length, it needs to carry around whether the last 4 bits are relevant
9896a8d0d3d2 rust-node: handling binary Node prefix
Georges Racinet <georges.racinet@octobus.net>
parents: 44228
diff changeset
148 /// or not.
9896a8d0d3d2 rust-node: handling binary Node prefix
Georges Racinet <georges.racinet@octobus.net>
parents: 44228
diff changeset
149 #[derive(Debug, PartialEq)]
9896a8d0d3d2 rust-node: handling binary Node prefix
Georges Racinet <georges.racinet@octobus.net>
parents: 44228
diff changeset
150 pub struct NodePrefix {
9896a8d0d3d2 rust-node: handling binary Node prefix
Georges Racinet <georges.racinet@octobus.net>
parents: 44228
diff changeset
151 buf: Vec<u8>,
9896a8d0d3d2 rust-node: handling binary Node prefix
Georges Racinet <georges.racinet@octobus.net>
parents: 44228
diff changeset
152 is_odd: bool,
9896a8d0d3d2 rust-node: handling binary Node prefix
Georges Racinet <georges.racinet@octobus.net>
parents: 44228
diff changeset
153 }
9896a8d0d3d2 rust-node: handling binary Node prefix
Georges Racinet <georges.racinet@octobus.net>
parents: 44228
diff changeset
154
9896a8d0d3d2 rust-node: handling binary Node prefix
Georges Racinet <georges.racinet@octobus.net>
parents: 44228
diff changeset
155 impl NodePrefix {
9896a8d0d3d2 rust-node: handling binary Node prefix
Georges Racinet <georges.racinet@octobus.net>
parents: 44228
diff changeset
156 /// Convert from hexadecimal string representation
9896a8d0d3d2 rust-node: handling binary Node prefix
Georges Racinet <georges.racinet@octobus.net>
parents: 44228
diff changeset
157 ///
9896a8d0d3d2 rust-node: handling binary Node prefix
Georges Racinet <georges.racinet@octobus.net>
parents: 44228
diff changeset
158 /// Similarly to `hex::decode`, can be used with Unicode string types
9896a8d0d3d2 rust-node: handling binary Node prefix
Georges Racinet <georges.racinet@octobus.net>
parents: 44228
diff changeset
159 /// (`String`, `&str`) as well as bytes.
9896a8d0d3d2 rust-node: handling binary Node prefix
Georges Racinet <georges.racinet@octobus.net>
parents: 44228
diff changeset
160 ///
9896a8d0d3d2 rust-node: handling binary Node prefix
Georges Racinet <georges.racinet@octobus.net>
parents: 44228
diff changeset
161 /// To be used in FFI and I/O only, in order to facilitate future
9896a8d0d3d2 rust-node: handling binary Node prefix
Georges Racinet <georges.racinet@octobus.net>
parents: 44228
diff changeset
162 /// changes of hash format.
9896a8d0d3d2 rust-node: handling binary Node prefix
Georges Racinet <georges.racinet@octobus.net>
parents: 44228
diff changeset
163 pub fn from_hex(hex: impl AsRef<[u8]>) -> Result<Self, NodeError> {
9896a8d0d3d2 rust-node: handling binary Node prefix
Georges Racinet <georges.racinet@octobus.net>
parents: 44228
diff changeset
164 let hex = hex.as_ref();
9896a8d0d3d2 rust-node: handling binary Node prefix
Georges Racinet <georges.racinet@octobus.net>
parents: 44228
diff changeset
165 let len = hex.len();
9896a8d0d3d2 rust-node: handling binary Node prefix
Georges Racinet <georges.racinet@octobus.net>
parents: 44228
diff changeset
166 if len > NODE_NYBBLES_LENGTH {
9896a8d0d3d2 rust-node: handling binary Node prefix
Georges Racinet <georges.racinet@octobus.net>
parents: 44228
diff changeset
167 return Err(NodeError::PrefixTooLong(
9896a8d0d3d2 rust-node: handling binary Node prefix
Georges Racinet <georges.racinet@octobus.net>
parents: 44228
diff changeset
168 String::from_utf8_lossy(hex).to_owned().to_string(),
9896a8d0d3d2 rust-node: handling binary Node prefix
Georges Racinet <georges.racinet@octobus.net>
parents: 44228
diff changeset
169 ));
9896a8d0d3d2 rust-node: handling binary Node prefix
Georges Racinet <georges.racinet@octobus.net>
parents: 44228
diff changeset
170 }
9896a8d0d3d2 rust-node: handling binary Node prefix
Georges Racinet <georges.racinet@octobus.net>
parents: 44228
diff changeset
171
9896a8d0d3d2 rust-node: handling binary Node prefix
Georges Racinet <georges.racinet@octobus.net>
parents: 44228
diff changeset
172 let is_odd = len % 2 == 1;
9896a8d0d3d2 rust-node: handling binary Node prefix
Georges Racinet <georges.racinet@octobus.net>
parents: 44228
diff changeset
173 let even_part = if is_odd { &hex[..len - 1] } else { hex };
9896a8d0d3d2 rust-node: handling binary Node prefix
Georges Racinet <georges.racinet@octobus.net>
parents: 44228
diff changeset
174 let mut buf: Vec<u8> = Vec::from_hex(&even_part)
9896a8d0d3d2 rust-node: handling binary Node prefix
Georges Racinet <georges.racinet@octobus.net>
parents: 44228
diff changeset
175 .map_err(|e| (e, String::from_utf8_lossy(hex)))?;
9896a8d0d3d2 rust-node: handling binary Node prefix
Georges Racinet <georges.racinet@octobus.net>
parents: 44228
diff changeset
176
9896a8d0d3d2 rust-node: handling binary Node prefix
Georges Racinet <georges.racinet@octobus.net>
parents: 44228
diff changeset
177 if is_odd {
9896a8d0d3d2 rust-node: handling binary Node prefix
Georges Racinet <georges.racinet@octobus.net>
parents: 44228
diff changeset
178 let latest_char = char::from(hex[len - 1]);
9896a8d0d3d2 rust-node: handling binary Node prefix
Georges Racinet <georges.racinet@octobus.net>
parents: 44228
diff changeset
179 let latest_nybble = latest_char.to_digit(16).ok_or_else(|| {
9896a8d0d3d2 rust-node: handling binary Node prefix
Georges Racinet <georges.racinet@octobus.net>
parents: 44228
diff changeset
180 (
9896a8d0d3d2 rust-node: handling binary Node prefix
Georges Racinet <georges.racinet@octobus.net>
parents: 44228
diff changeset
181 FromHexError::InvalidHexCharacter {
9896a8d0d3d2 rust-node: handling binary Node prefix
Georges Racinet <georges.racinet@octobus.net>
parents: 44228
diff changeset
182 c: latest_char,
9896a8d0d3d2 rust-node: handling binary Node prefix
Georges Racinet <georges.racinet@octobus.net>
parents: 44228
diff changeset
183 index: len - 1,
9896a8d0d3d2 rust-node: handling binary Node prefix
Georges Racinet <georges.racinet@octobus.net>
parents: 44228
diff changeset
184 },
9896a8d0d3d2 rust-node: handling binary Node prefix
Georges Racinet <georges.racinet@octobus.net>
parents: 44228
diff changeset
185 String::from_utf8_lossy(hex),
9896a8d0d3d2 rust-node: handling binary Node prefix
Georges Racinet <georges.racinet@octobus.net>
parents: 44228
diff changeset
186 )
9896a8d0d3d2 rust-node: handling binary Node prefix
Georges Racinet <georges.racinet@octobus.net>
parents: 44228
diff changeset
187 })? as u8;
9896a8d0d3d2 rust-node: handling binary Node prefix
Georges Racinet <georges.racinet@octobus.net>
parents: 44228
diff changeset
188 buf.push(latest_nybble << 4);
9896a8d0d3d2 rust-node: handling binary Node prefix
Georges Racinet <georges.racinet@octobus.net>
parents: 44228
diff changeset
189 }
9896a8d0d3d2 rust-node: handling binary Node prefix
Georges Racinet <georges.racinet@octobus.net>
parents: 44228
diff changeset
190 Ok(NodePrefix { buf, is_odd })
9896a8d0d3d2 rust-node: handling binary Node prefix
Georges Racinet <georges.racinet@octobus.net>
parents: 44228
diff changeset
191 }
9896a8d0d3d2 rust-node: handling binary Node prefix
Georges Racinet <georges.racinet@octobus.net>
parents: 44228
diff changeset
192
9896a8d0d3d2 rust-node: handling binary Node prefix
Georges Racinet <georges.racinet@octobus.net>
parents: 44228
diff changeset
193 pub fn borrow(&self) -> NodePrefixRef {
9896a8d0d3d2 rust-node: handling binary Node prefix
Georges Racinet <georges.racinet@octobus.net>
parents: 44228
diff changeset
194 NodePrefixRef {
9896a8d0d3d2 rust-node: handling binary Node prefix
Georges Racinet <georges.racinet@octobus.net>
parents: 44228
diff changeset
195 buf: &self.buf,
9896a8d0d3d2 rust-node: handling binary Node prefix
Georges Racinet <georges.racinet@octobus.net>
parents: 44228
diff changeset
196 is_odd: self.is_odd,
9896a8d0d3d2 rust-node: handling binary Node prefix
Georges Racinet <georges.racinet@octobus.net>
parents: 44228
diff changeset
197 }
9896a8d0d3d2 rust-node: handling binary Node prefix
Georges Racinet <georges.racinet@octobus.net>
parents: 44228
diff changeset
198 }
9896a8d0d3d2 rust-node: handling binary Node prefix
Georges Racinet <georges.racinet@octobus.net>
parents: 44228
diff changeset
199 }
9896a8d0d3d2 rust-node: handling binary Node prefix
Georges Racinet <georges.racinet@octobus.net>
parents: 44228
diff changeset
200
9896a8d0d3d2 rust-node: handling binary Node prefix
Georges Racinet <georges.racinet@octobus.net>
parents: 44228
diff changeset
201 #[derive(Clone, Debug, PartialEq)]
9896a8d0d3d2 rust-node: handling binary Node prefix
Georges Racinet <georges.racinet@octobus.net>
parents: 44228
diff changeset
202 pub struct NodePrefixRef<'a> {
9896a8d0d3d2 rust-node: handling binary Node prefix
Georges Racinet <georges.racinet@octobus.net>
parents: 44228
diff changeset
203 buf: &'a [u8],
9896a8d0d3d2 rust-node: handling binary Node prefix
Georges Racinet <georges.racinet@octobus.net>
parents: 44228
diff changeset
204 is_odd: bool,
9896a8d0d3d2 rust-node: handling binary Node prefix
Georges Racinet <georges.racinet@octobus.net>
parents: 44228
diff changeset
205 }
9896a8d0d3d2 rust-node: handling binary Node prefix
Georges Racinet <georges.racinet@octobus.net>
parents: 44228
diff changeset
206
9896a8d0d3d2 rust-node: handling binary Node prefix
Georges Racinet <georges.racinet@octobus.net>
parents: 44228
diff changeset
207 impl<'a> NodePrefixRef<'a> {
9896a8d0d3d2 rust-node: handling binary Node prefix
Georges Racinet <georges.racinet@octobus.net>
parents: 44228
diff changeset
208 pub fn len(&self) -> usize {
9896a8d0d3d2 rust-node: handling binary Node prefix
Georges Racinet <georges.racinet@octobus.net>
parents: 44228
diff changeset
209 if self.is_odd {
9896a8d0d3d2 rust-node: handling binary Node prefix
Georges Racinet <georges.racinet@octobus.net>
parents: 44228
diff changeset
210 self.buf.len() * 2 - 1
9896a8d0d3d2 rust-node: handling binary Node prefix
Georges Racinet <georges.racinet@octobus.net>
parents: 44228
diff changeset
211 } else {
9896a8d0d3d2 rust-node: handling binary Node prefix
Georges Racinet <georges.racinet@octobus.net>
parents: 44228
diff changeset
212 self.buf.len() * 2
9896a8d0d3d2 rust-node: handling binary Node prefix
Georges Racinet <georges.racinet@octobus.net>
parents: 44228
diff changeset
213 }
9896a8d0d3d2 rust-node: handling binary Node prefix
Georges Racinet <georges.racinet@octobus.net>
parents: 44228
diff changeset
214 }
9896a8d0d3d2 rust-node: handling binary Node prefix
Georges Racinet <georges.racinet@octobus.net>
parents: 44228
diff changeset
215
44998
26114bd6ec60 rust: do a clippy pass
Rapha?l Gom?s <rgomes@octobus.net>
parents: 44512
diff changeset
216 pub fn is_empty(&self) -> bool {
26114bd6ec60 rust: do a clippy pass
Rapha?l Gom?s <rgomes@octobus.net>
parents: 44512
diff changeset
217 self.len() == 0
26114bd6ec60 rust: do a clippy pass
Rapha?l Gom?s <rgomes@octobus.net>
parents: 44512
diff changeset
218 }
26114bd6ec60 rust: do a clippy pass
Rapha?l Gom?s <rgomes@octobus.net>
parents: 44512
diff changeset
219
44257
9896a8d0d3d2 rust-node: handling binary Node prefix
Georges Racinet <georges.racinet@octobus.net>
parents: 44228
diff changeset
220 pub fn is_prefix_of(&self, node: &Node) -> bool {
9896a8d0d3d2 rust-node: handling binary Node prefix
Georges Racinet <georges.racinet@octobus.net>
parents: 44228
diff changeset
221 if self.is_odd {
9896a8d0d3d2 rust-node: handling binary Node prefix
Georges Racinet <georges.racinet@octobus.net>
parents: 44228
diff changeset
222 let buf = self.buf;
9896a8d0d3d2 rust-node: handling binary Node prefix
Georges Racinet <georges.racinet@octobus.net>
parents: 44228
diff changeset
223 let last_pos = buf.len() - 1;
9896a8d0d3d2 rust-node: handling binary Node prefix
Georges Racinet <georges.racinet@octobus.net>
parents: 44228
diff changeset
224 node.data.starts_with(buf.split_at(last_pos).0)
9896a8d0d3d2 rust-node: handling binary Node prefix
Georges Racinet <georges.racinet@octobus.net>
parents: 44228
diff changeset
225 && node.data[last_pos] >> 4 == buf[last_pos] >> 4
9896a8d0d3d2 rust-node: handling binary Node prefix
Georges Racinet <georges.racinet@octobus.net>
parents: 44228
diff changeset
226 } else {
9896a8d0d3d2 rust-node: handling binary Node prefix
Georges Racinet <georges.racinet@octobus.net>
parents: 44228
diff changeset
227 node.data.starts_with(self.buf)
9896a8d0d3d2 rust-node: handling binary Node prefix
Georges Racinet <georges.racinet@octobus.net>
parents: 44228
diff changeset
228 }
9896a8d0d3d2 rust-node: handling binary Node prefix
Georges Racinet <georges.racinet@octobus.net>
parents: 44228
diff changeset
229 }
9896a8d0d3d2 rust-node: handling binary Node prefix
Georges Racinet <georges.racinet@octobus.net>
parents: 44228
diff changeset
230
9896a8d0d3d2 rust-node: handling binary Node prefix
Georges Racinet <georges.racinet@octobus.net>
parents: 44228
diff changeset
231 /// Retrieve the `i`th half-byte from the prefix.
9896a8d0d3d2 rust-node: handling binary Node prefix
Georges Racinet <georges.racinet@octobus.net>
parents: 44228
diff changeset
232 ///
9896a8d0d3d2 rust-node: handling binary Node prefix
Georges Racinet <georges.racinet@octobus.net>
parents: 44228
diff changeset
233 /// This is also the `i`th hexadecimal digit in numeric form,
9896a8d0d3d2 rust-node: handling binary Node prefix
Georges Racinet <georges.racinet@octobus.net>
parents: 44228
diff changeset
234 /// also called a [nybble](https://en.wikipedia.org/wiki/Nibble).
9896a8d0d3d2 rust-node: handling binary Node prefix
Georges Racinet <georges.racinet@octobus.net>
parents: 44228
diff changeset
235 pub fn get_nybble(&self, i: usize) -> u8 {
44262
be52b7372ec2 rust-node: avoid meaningless read at the end of odd prefix
Georges Racinet <georges.racinet@octobus.net>
parents: 44258
diff changeset
236 assert!(i < self.len());
44257
9896a8d0d3d2 rust-node: handling binary Node prefix
Georges Racinet <georges.racinet@octobus.net>
parents: 44228
diff changeset
237 get_nybble(self.buf, i)
9896a8d0d3d2 rust-node: handling binary Node prefix
Georges Racinet <georges.racinet@octobus.net>
parents: 44228
diff changeset
238 }
44419
5ac1eecc9c64 rust-nodemap: core implementation for shortest
Georges Racinet <georges.racinet@octobus.net>
parents: 44262
diff changeset
239
5ac1eecc9c64 rust-nodemap: core implementation for shortest
Georges Racinet <georges.racinet@octobus.net>
parents: 44262
diff changeset
240 /// Return the index first nybble that's different from `node`
5ac1eecc9c64 rust-nodemap: core implementation for shortest
Georges Racinet <georges.racinet@octobus.net>
parents: 44262
diff changeset
241 ///
5ac1eecc9c64 rust-nodemap: core implementation for shortest
Georges Racinet <georges.racinet@octobus.net>
parents: 44262
diff changeset
242 /// If the return value is `None` that means that `self` is
5ac1eecc9c64 rust-nodemap: core implementation for shortest
Georges Racinet <georges.racinet@octobus.net>
parents: 44262
diff changeset
243 /// a prefix of `node`, but the current method is a bit slower
5ac1eecc9c64 rust-nodemap: core implementation for shortest
Georges Racinet <georges.racinet@octobus.net>
parents: 44262
diff changeset
244 /// than `is_prefix_of`.
5ac1eecc9c64 rust-nodemap: core implementation for shortest
Georges Racinet <georges.racinet@octobus.net>
parents: 44262
diff changeset
245 ///
5ac1eecc9c64 rust-nodemap: core implementation for shortest
Georges Racinet <georges.racinet@octobus.net>
parents: 44262
diff changeset
246 /// Returned index is as in `get_nybble`, i.e., starting at 0.
5ac1eecc9c64 rust-nodemap: core implementation for shortest
Georges Racinet <georges.racinet@octobus.net>
parents: 44262
diff changeset
247 pub fn first_different_nybble(&self, node: &Node) -> Option<usize> {
5ac1eecc9c64 rust-nodemap: core implementation for shortest
Georges Racinet <georges.racinet@octobus.net>
parents: 44262
diff changeset
248 let buf = self.buf;
5ac1eecc9c64 rust-nodemap: core implementation for shortest
Georges Racinet <georges.racinet@octobus.net>
parents: 44262
diff changeset
249 let until = if self.is_odd {
5ac1eecc9c64 rust-nodemap: core implementation for shortest
Georges Racinet <georges.racinet@octobus.net>
parents: 44262
diff changeset
250 buf.len() - 1
5ac1eecc9c64 rust-nodemap: core implementation for shortest
Georges Racinet <georges.racinet@octobus.net>
parents: 44262
diff changeset
251 } else {
5ac1eecc9c64 rust-nodemap: core implementation for shortest
Georges Racinet <georges.racinet@octobus.net>
parents: 44262
diff changeset
252 buf.len()
5ac1eecc9c64 rust-nodemap: core implementation for shortest
Georges Racinet <georges.racinet@octobus.net>
parents: 44262
diff changeset
253 };
44998
26114bd6ec60 rust: do a clippy pass
Rapha?l Gom?s <rgomes@octobus.net>
parents: 44512
diff changeset
254 for (i, item) in buf.iter().enumerate().take(until) {
26114bd6ec60 rust: do a clippy pass
Rapha?l Gom?s <rgomes@octobus.net>
parents: 44512
diff changeset
255 if *item != node.data[i] {
26114bd6ec60 rust: do a clippy pass
Rapha?l Gom?s <rgomes@octobus.net>
parents: 44512
diff changeset
256 return if *item & 0xf0 == node.data[i] & 0xf0 {
26114bd6ec60 rust: do a clippy pass
Rapha?l Gom?s <rgomes@octobus.net>
parents: 44512
diff changeset
257 Some(2 * i + 1)
44419
5ac1eecc9c64 rust-nodemap: core implementation for shortest
Georges Racinet <georges.racinet@octobus.net>
parents: 44262
diff changeset
258 } else {
44998
26114bd6ec60 rust: do a clippy pass
Rapha?l Gom?s <rgomes@octobus.net>
parents: 44512
diff changeset
259 Some(2 * i)
26114bd6ec60 rust: do a clippy pass
Rapha?l Gom?s <rgomes@octobus.net>
parents: 44512
diff changeset
260 };
44419
5ac1eecc9c64 rust-nodemap: core implementation for shortest
Georges Racinet <georges.racinet@octobus.net>
parents: 44262
diff changeset
261 }
5ac1eecc9c64 rust-nodemap: core implementation for shortest
Georges Racinet <georges.racinet@octobus.net>
parents: 44262
diff changeset
262 }
5ac1eecc9c64 rust-nodemap: core implementation for shortest
Georges Racinet <georges.racinet@octobus.net>
parents: 44262
diff changeset
263 if self.is_odd && buf[until] & 0xf0 != node.data[until] & 0xf0 {
5ac1eecc9c64 rust-nodemap: core implementation for shortest
Georges Racinet <georges.racinet@octobus.net>
parents: 44262
diff changeset
264 Some(until * 2)
5ac1eecc9c64 rust-nodemap: core implementation for shortest
Georges Racinet <georges.racinet@octobus.net>
parents: 44262
diff changeset
265 } else {
5ac1eecc9c64 rust-nodemap: core implementation for shortest
Georges Racinet <georges.racinet@octobus.net>
parents: 44262
diff changeset
266 None
5ac1eecc9c64 rust-nodemap: core implementation for shortest
Georges Racinet <georges.racinet@octobus.net>
parents: 44262
diff changeset
267 }
5ac1eecc9c64 rust-nodemap: core implementation for shortest
Georges Racinet <georges.racinet@octobus.net>
parents: 44262
diff changeset
268 }
44257
9896a8d0d3d2 rust-node: handling binary Node prefix
Georges Racinet <georges.racinet@octobus.net>
parents: 44228
diff changeset
269 }
9896a8d0d3d2 rust-node: handling binary Node prefix
Georges Racinet <georges.racinet@octobus.net>
parents: 44228
diff changeset
270
9896a8d0d3d2 rust-node: handling binary Node prefix
Georges Racinet <georges.racinet@octobus.net>
parents: 44228
diff changeset
271 /// A shortcut for full `Node` references
9896a8d0d3d2 rust-node: handling binary Node prefix
Georges Racinet <georges.racinet@octobus.net>
parents: 44228
diff changeset
272 impl<'a> From<&'a Node> for NodePrefixRef<'a> {
9896a8d0d3d2 rust-node: handling binary Node prefix
Georges Racinet <georges.racinet@octobus.net>
parents: 44228
diff changeset
273 fn from(node: &'a Node) -> Self {
9896a8d0d3d2 rust-node: handling binary Node prefix
Georges Racinet <georges.racinet@octobus.net>
parents: 44228
diff changeset
274 NodePrefixRef {
9896a8d0d3d2 rust-node: handling binary Node prefix
Georges Racinet <georges.racinet@octobus.net>
parents: 44228
diff changeset
275 buf: &node.data,
9896a8d0d3d2 rust-node: handling binary Node prefix
Georges Racinet <georges.racinet@octobus.net>
parents: 44228
diff changeset
276 is_odd: false,
44228
7f86426fdd2c rust-node: binary Node ID and conversion utilities
Georges Racinet <georges.racinet@octobus.net>
parents:
diff changeset
277 }
7f86426fdd2c rust-node: binary Node ID and conversion utilities
Georges Racinet <georges.racinet@octobus.net>
parents:
diff changeset
278 }
7f86426fdd2c rust-node: binary Node ID and conversion utilities
Georges Racinet <georges.racinet@octobus.net>
parents:
diff changeset
279 }
7f86426fdd2c rust-node: binary Node ID and conversion utilities
Georges Racinet <georges.racinet@octobus.net>
parents:
diff changeset
280
7f86426fdd2c rust-node: binary Node ID and conversion utilities
Georges Racinet <georges.racinet@octobus.net>
parents:
diff changeset
281 #[cfg(test)]
7f86426fdd2c rust-node: binary Node ID and conversion utilities
Georges Racinet <georges.racinet@octobus.net>
parents:
diff changeset
282 mod tests {
7f86426fdd2c rust-node: binary Node ID and conversion utilities
Georges Racinet <georges.racinet@octobus.net>
parents:
diff changeset
283 use super::*;
7f86426fdd2c rust-node: binary Node ID and conversion utilities
Georges Racinet <georges.racinet@octobus.net>
parents:
diff changeset
284
7f86426fdd2c rust-node: binary Node ID and conversion utilities
Georges Racinet <georges.racinet@octobus.net>
parents:
diff changeset
285 fn sample_node() -> Node {
7f86426fdd2c rust-node: binary Node ID and conversion utilities
Georges Racinet <georges.racinet@octobus.net>
parents:
diff changeset
286 let mut data = [0; NODE_BYTES_LENGTH];
7f86426fdd2c rust-node: binary Node ID and conversion utilities
Georges Racinet <georges.racinet@octobus.net>
parents:
diff changeset
287 data.copy_from_slice(&[
7f86426fdd2c rust-node: binary Node ID and conversion utilities
Georges Racinet <georges.racinet@octobus.net>
parents:
diff changeset
288 0x01, 0x23, 0x45, 0x67, 0x89, 0xab, 0xcd, 0xef, 0xfe, 0xdc, 0xba,
7f86426fdd2c rust-node: binary Node ID and conversion utilities
Georges Racinet <georges.racinet@octobus.net>
parents:
diff changeset
289 0x98, 0x76, 0x54, 0x32, 0x10, 0xde, 0xad, 0xbe, 0xef,
7f86426fdd2c rust-node: binary Node ID and conversion utilities
Georges Racinet <georges.racinet@octobus.net>
parents:
diff changeset
290 ]);
7f86426fdd2c rust-node: binary Node ID and conversion utilities
Georges Racinet <georges.racinet@octobus.net>
parents:
diff changeset
291 data.into()
7f86426fdd2c rust-node: binary Node ID and conversion utilities
Georges Racinet <georges.racinet@octobus.net>
parents:
diff changeset
292 }
7f86426fdd2c rust-node: binary Node ID and conversion utilities
Georges Racinet <georges.racinet@octobus.net>
parents:
diff changeset
293
7f86426fdd2c rust-node: binary Node ID and conversion utilities
Georges Racinet <georges.racinet@octobus.net>
parents:
diff changeset
294 /// Pad an hexadecimal string to reach `NODE_NYBBLES_LENGTH`
7f86426fdd2c rust-node: binary Node ID and conversion utilities
Georges Racinet <georges.racinet@octobus.net>
parents:
diff changeset
295 ///
7f86426fdd2c rust-node: binary Node ID and conversion utilities
Georges Racinet <georges.racinet@octobus.net>
parents:
diff changeset
296 /// The padding is made with zeros
44258
e52401a95b94 rust-nodemap: NodeMap trait with simplest implementation
Georges Racinet <georges.racinet@octobus.net>
parents: 44257
diff changeset
297 pub fn hex_pad_right(hex: &str) -> String {
44228
7f86426fdd2c rust-node: binary Node ID and conversion utilities
Georges Racinet <georges.racinet@octobus.net>
parents:
diff changeset
298 let mut res = hex.to_string();
7f86426fdd2c rust-node: binary Node ID and conversion utilities
Georges Racinet <georges.racinet@octobus.net>
parents:
diff changeset
299 while res.len() < NODE_NYBBLES_LENGTH {
7f86426fdd2c rust-node: binary Node ID and conversion utilities
Georges Racinet <georges.racinet@octobus.net>
parents:
diff changeset
300 res.push('0');
7f86426fdd2c rust-node: binary Node ID and conversion utilities
Georges Racinet <georges.racinet@octobus.net>
parents:
diff changeset
301 }
7f86426fdd2c rust-node: binary Node ID and conversion utilities
Georges Racinet <georges.racinet@octobus.net>
parents:
diff changeset
302 res
7f86426fdd2c rust-node: binary Node ID and conversion utilities
Georges Racinet <georges.racinet@octobus.net>
parents:
diff changeset
303 }
7f86426fdd2c rust-node: binary Node ID and conversion utilities
Georges Racinet <georges.racinet@octobus.net>
parents:
diff changeset
304
7f86426fdd2c rust-node: binary Node ID and conversion utilities
Georges Racinet <georges.racinet@octobus.net>
parents:
diff changeset
305 fn sample_node_hex() -> String {
7f86426fdd2c rust-node: binary Node ID and conversion utilities
Georges Racinet <georges.racinet@octobus.net>
parents:
diff changeset
306 hex_pad_right("0123456789abcdeffedcba9876543210deadbeef")
7f86426fdd2c rust-node: binary Node ID and conversion utilities
Georges Racinet <georges.racinet@octobus.net>
parents:
diff changeset
307 }
7f86426fdd2c rust-node: binary Node ID and conversion utilities
Georges Racinet <georges.racinet@octobus.net>
parents:
diff changeset
308
7f86426fdd2c rust-node: binary Node ID and conversion utilities
Georges Racinet <georges.racinet@octobus.net>
parents:
diff changeset
309 #[test]
7f86426fdd2c rust-node: binary Node ID and conversion utilities
Georges Racinet <georges.racinet@octobus.net>
parents:
diff changeset
310 fn test_node_from_hex() {
7f86426fdd2c rust-node: binary Node ID and conversion utilities
Georges Racinet <georges.racinet@octobus.net>
parents:
diff changeset
311 assert_eq!(Node::from_hex(&sample_node_hex()), Ok(sample_node()));
7f86426fdd2c rust-node: binary Node ID and conversion utilities
Georges Racinet <georges.racinet@octobus.net>
parents:
diff changeset
312
7f86426fdd2c rust-node: binary Node ID and conversion utilities
Georges Racinet <georges.racinet@octobus.net>
parents:
diff changeset
313 let mut short = hex_pad_right("0123");
7f86426fdd2c rust-node: binary Node ID and conversion utilities
Georges Racinet <georges.racinet@octobus.net>
parents:
diff changeset
314 short.pop();
7f86426fdd2c rust-node: binary Node ID and conversion utilities
Georges Racinet <georges.racinet@octobus.net>
parents:
diff changeset
315 short.pop();
7f86426fdd2c rust-node: binary Node ID and conversion utilities
Georges Racinet <georges.racinet@octobus.net>
parents:
diff changeset
316 assert_eq!(
7f86426fdd2c rust-node: binary Node ID and conversion utilities
Georges Racinet <georges.racinet@octobus.net>
parents:
diff changeset
317 Node::from_hex(&short),
7f86426fdd2c rust-node: binary Node ID and conversion utilities
Georges Racinet <georges.racinet@octobus.net>
parents:
diff changeset
318 Err(NodeError::ExactLengthRequired(NODE_NYBBLES_LENGTH, short)),
7f86426fdd2c rust-node: binary Node ID and conversion utilities
Georges Racinet <georges.racinet@octobus.net>
parents:
diff changeset
319 );
7f86426fdd2c rust-node: binary Node ID and conversion utilities
Georges Racinet <georges.racinet@octobus.net>
parents:
diff changeset
320
7f86426fdd2c rust-node: binary Node ID and conversion utilities
Georges Racinet <georges.racinet@octobus.net>
parents:
diff changeset
321 let not_hex = hex_pad_right("012... oops");
7f86426fdd2c rust-node: binary Node ID and conversion utilities
Georges Racinet <georges.racinet@octobus.net>
parents:
diff changeset
322 assert_eq!(
7f86426fdd2c rust-node: binary Node ID and conversion utilities
Georges Racinet <georges.racinet@octobus.net>
parents:
diff changeset
323 Node::from_hex(&not_hex),
7f86426fdd2c rust-node: binary Node ID and conversion utilities
Georges Racinet <georges.racinet@octobus.net>
parents:
diff changeset
324 Err(NodeError::HexError(
7f86426fdd2c rust-node: binary Node ID and conversion utilities
Georges Racinet <georges.racinet@octobus.net>
parents:
diff changeset
325 FromHexError::InvalidHexCharacter { c: '.', index: 3 },
7f86426fdd2c rust-node: binary Node ID and conversion utilities
Georges Racinet <georges.racinet@octobus.net>
parents:
diff changeset
326 not_hex,
7f86426fdd2c rust-node: binary Node ID and conversion utilities
Georges Racinet <georges.racinet@octobus.net>
parents:
diff changeset
327 )),
7f86426fdd2c rust-node: binary Node ID and conversion utilities
Georges Racinet <georges.racinet@octobus.net>
parents:
diff changeset
328 );
7f86426fdd2c rust-node: binary Node ID and conversion utilities
Georges Racinet <georges.racinet@octobus.net>
parents:
diff changeset
329 }
7f86426fdd2c rust-node: binary Node ID and conversion utilities
Georges Racinet <georges.racinet@octobus.net>
parents:
diff changeset
330
7f86426fdd2c rust-node: binary Node ID and conversion utilities
Georges Racinet <georges.racinet@octobus.net>
parents:
diff changeset
331 #[test]
7f86426fdd2c rust-node: binary Node ID and conversion utilities
Georges Racinet <georges.racinet@octobus.net>
parents:
diff changeset
332 fn test_node_encode_hex() {
7f86426fdd2c rust-node: binary Node ID and conversion utilities
Georges Racinet <georges.racinet@octobus.net>
parents:
diff changeset
333 assert_eq!(sample_node().encode_hex(), sample_node_hex());
7f86426fdd2c rust-node: binary Node ID and conversion utilities
Georges Racinet <georges.racinet@octobus.net>
parents:
diff changeset
334 }
44257
9896a8d0d3d2 rust-node: handling binary Node prefix
Georges Racinet <georges.racinet@octobus.net>
parents: 44228
diff changeset
335
9896a8d0d3d2 rust-node: handling binary Node prefix
Georges Racinet <georges.racinet@octobus.net>
parents: 44228
diff changeset
336 #[test]
9896a8d0d3d2 rust-node: handling binary Node prefix
Georges Racinet <georges.racinet@octobus.net>
parents: 44228
diff changeset
337 fn test_prefix_from_hex() -> Result<(), NodeError> {
9896a8d0d3d2 rust-node: handling binary Node prefix
Georges Racinet <georges.racinet@octobus.net>
parents: 44228
diff changeset
338 assert_eq!(
9896a8d0d3d2 rust-node: handling binary Node prefix
Georges Racinet <georges.racinet@octobus.net>
parents: 44228
diff changeset
339 NodePrefix::from_hex("0e1")?,
9896a8d0d3d2 rust-node: handling binary Node prefix
Georges Racinet <georges.racinet@octobus.net>
parents: 44228
diff changeset
340 NodePrefix {
9896a8d0d3d2 rust-node: handling binary Node prefix
Georges Racinet <georges.racinet@octobus.net>
parents: 44228
diff changeset
341 buf: vec![14, 16],
9896a8d0d3d2 rust-node: handling binary Node prefix
Georges Racinet <georges.racinet@octobus.net>
parents: 44228
diff changeset
342 is_odd: true
9896a8d0d3d2 rust-node: handling binary Node prefix
Georges Racinet <georges.racinet@octobus.net>
parents: 44228
diff changeset
343 }
9896a8d0d3d2 rust-node: handling binary Node prefix
Georges Racinet <georges.racinet@octobus.net>
parents: 44228
diff changeset
344 );
9896a8d0d3d2 rust-node: handling binary Node prefix
Georges Racinet <georges.racinet@octobus.net>
parents: 44228
diff changeset
345 assert_eq!(
9896a8d0d3d2 rust-node: handling binary Node prefix
Georges Racinet <georges.racinet@octobus.net>
parents: 44228
diff changeset
346 NodePrefix::from_hex("0e1a")?,
9896a8d0d3d2 rust-node: handling binary Node prefix
Georges Racinet <georges.racinet@octobus.net>
parents: 44228
diff changeset
347 NodePrefix {
9896a8d0d3d2 rust-node: handling binary Node prefix
Georges Racinet <georges.racinet@octobus.net>
parents: 44228
diff changeset
348 buf: vec![14, 26],
9896a8d0d3d2 rust-node: handling binary Node prefix
Georges Racinet <georges.racinet@octobus.net>
parents: 44228
diff changeset
349 is_odd: false
9896a8d0d3d2 rust-node: handling binary Node prefix
Georges Racinet <georges.racinet@octobus.net>
parents: 44228
diff changeset
350 }
9896a8d0d3d2 rust-node: handling binary Node prefix
Georges Racinet <georges.racinet@octobus.net>
parents: 44228
diff changeset
351 );
9896a8d0d3d2 rust-node: handling binary Node prefix
Georges Racinet <georges.racinet@octobus.net>
parents: 44228
diff changeset
352
9896a8d0d3d2 rust-node: handling binary Node prefix
Georges Racinet <georges.racinet@octobus.net>
parents: 44228
diff changeset
353 // checking limit case
9896a8d0d3d2 rust-node: handling binary Node prefix
Georges Racinet <georges.racinet@octobus.net>
parents: 44228
diff changeset
354 let node_as_vec = sample_node().data.iter().cloned().collect();
9896a8d0d3d2 rust-node: handling binary Node prefix
Georges Racinet <georges.racinet@octobus.net>
parents: 44228
diff changeset
355 assert_eq!(
9896a8d0d3d2 rust-node: handling binary Node prefix
Georges Racinet <georges.racinet@octobus.net>
parents: 44228
diff changeset
356 NodePrefix::from_hex(sample_node_hex())?,
9896a8d0d3d2 rust-node: handling binary Node prefix
Georges Racinet <georges.racinet@octobus.net>
parents: 44228
diff changeset
357 NodePrefix {
9896a8d0d3d2 rust-node: handling binary Node prefix
Georges Racinet <georges.racinet@octobus.net>
parents: 44228
diff changeset
358 buf: node_as_vec,
9896a8d0d3d2 rust-node: handling binary Node prefix
Georges Racinet <georges.racinet@octobus.net>
parents: 44228
diff changeset
359 is_odd: false
9896a8d0d3d2 rust-node: handling binary Node prefix
Georges Racinet <georges.racinet@octobus.net>
parents: 44228
diff changeset
360 }
9896a8d0d3d2 rust-node: handling binary Node prefix
Georges Racinet <georges.racinet@octobus.net>
parents: 44228
diff changeset
361 );
9896a8d0d3d2 rust-node: handling binary Node prefix
Georges Racinet <georges.racinet@octobus.net>
parents: 44228
diff changeset
362
9896a8d0d3d2 rust-node: handling binary Node prefix
Georges Racinet <georges.racinet@octobus.net>
parents: 44228
diff changeset
363 Ok(())
9896a8d0d3d2 rust-node: handling binary Node prefix
Georges Racinet <georges.racinet@octobus.net>
parents: 44228
diff changeset
364 }
9896a8d0d3d2 rust-node: handling binary Node prefix
Georges Racinet <georges.racinet@octobus.net>
parents: 44228
diff changeset
365
9896a8d0d3d2 rust-node: handling binary Node prefix
Georges Racinet <georges.racinet@octobus.net>
parents: 44228
diff changeset
366 #[test]
9896a8d0d3d2 rust-node: handling binary Node prefix
Georges Racinet <georges.racinet@octobus.net>
parents: 44228
diff changeset
367 fn test_prefix_from_hex_errors() {
9896a8d0d3d2 rust-node: handling binary Node prefix
Georges Racinet <georges.racinet@octobus.net>
parents: 44228
diff changeset
368 assert_eq!(
9896a8d0d3d2 rust-node: handling binary Node prefix
Georges Racinet <georges.racinet@octobus.net>
parents: 44228
diff changeset
369 NodePrefix::from_hex("testgr"),
9896a8d0d3d2 rust-node: handling binary Node prefix
Georges Racinet <georges.racinet@octobus.net>
parents: 44228
diff changeset
370 Err(NodeError::HexError(
9896a8d0d3d2 rust-node: handling binary Node prefix
Georges Racinet <georges.racinet@octobus.net>
parents: 44228
diff changeset
371 FromHexError::InvalidHexCharacter { c: 't', index: 0 },
9896a8d0d3d2 rust-node: handling binary Node prefix
Georges Racinet <georges.racinet@octobus.net>
parents: 44228
diff changeset
372 "testgr".to_string()
9896a8d0d3d2 rust-node: handling binary Node prefix
Georges Racinet <georges.racinet@octobus.net>
parents: 44228
diff changeset
373 ))
9896a8d0d3d2 rust-node: handling binary Node prefix
Georges Racinet <georges.racinet@octobus.net>
parents: 44228
diff changeset
374 );
9896a8d0d3d2 rust-node: handling binary Node prefix
Georges Racinet <georges.racinet@octobus.net>
parents: 44228
diff changeset
375 let mut long = NULL_NODE.encode_hex();
9896a8d0d3d2 rust-node: handling binary Node prefix
Georges Racinet <georges.racinet@octobus.net>
parents: 44228
diff changeset
376 long.push('c');
9896a8d0d3d2 rust-node: handling binary Node prefix
Georges Racinet <georges.racinet@octobus.net>
parents: 44228
diff changeset
377 match NodePrefix::from_hex(&long)
9896a8d0d3d2 rust-node: handling binary Node prefix
Georges Racinet <georges.racinet@octobus.net>
parents: 44228
diff changeset
378 .expect_err("should be refused as too long")
9896a8d0d3d2 rust-node: handling binary Node prefix
Georges Racinet <georges.racinet@octobus.net>
parents: 44228
diff changeset
379 {
9896a8d0d3d2 rust-node: handling binary Node prefix
Georges Racinet <georges.racinet@octobus.net>
parents: 44228
diff changeset
380 NodeError::PrefixTooLong(s) => assert_eq!(s, long),
9896a8d0d3d2 rust-node: handling binary Node prefix
Georges Racinet <georges.racinet@octobus.net>
parents: 44228
diff changeset
381 err => panic!(format!("Should have been TooLong, got {:?}", err)),
9896a8d0d3d2 rust-node: handling binary Node prefix
Georges Racinet <georges.racinet@octobus.net>
parents: 44228
diff changeset
382 }
9896a8d0d3d2 rust-node: handling binary Node prefix
Georges Racinet <georges.racinet@octobus.net>
parents: 44228
diff changeset
383 }
9896a8d0d3d2 rust-node: handling binary Node prefix
Georges Racinet <georges.racinet@octobus.net>
parents: 44228
diff changeset
384
9896a8d0d3d2 rust-node: handling binary Node prefix
Georges Racinet <georges.racinet@octobus.net>
parents: 44228
diff changeset
385 #[test]
9896a8d0d3d2 rust-node: handling binary Node prefix
Georges Racinet <georges.racinet@octobus.net>
parents: 44228
diff changeset
386 fn test_is_prefix_of() -> Result<(), NodeError> {
9896a8d0d3d2 rust-node: handling binary Node prefix
Georges Racinet <georges.racinet@octobus.net>
parents: 44228
diff changeset
387 let mut node_data = [0; NODE_BYTES_LENGTH];
9896a8d0d3d2 rust-node: handling binary Node prefix
Georges Racinet <georges.racinet@octobus.net>
parents: 44228
diff changeset
388 node_data[0] = 0x12;
9896a8d0d3d2 rust-node: handling binary Node prefix
Georges Racinet <georges.racinet@octobus.net>
parents: 44228
diff changeset
389 node_data[1] = 0xca;
9896a8d0d3d2 rust-node: handling binary Node prefix
Georges Racinet <georges.racinet@octobus.net>
parents: 44228
diff changeset
390 let node = Node::from(node_data);
9896a8d0d3d2 rust-node: handling binary Node prefix
Georges Racinet <georges.racinet@octobus.net>
parents: 44228
diff changeset
391 assert!(NodePrefix::from_hex("12")?.borrow().is_prefix_of(&node));
9896a8d0d3d2 rust-node: handling binary Node prefix
Georges Racinet <georges.racinet@octobus.net>
parents: 44228
diff changeset
392 assert!(!NodePrefix::from_hex("1a")?.borrow().is_prefix_of(&node));
9896a8d0d3d2 rust-node: handling binary Node prefix
Georges Racinet <georges.racinet@octobus.net>
parents: 44228
diff changeset
393 assert!(NodePrefix::from_hex("12c")?.borrow().is_prefix_of(&node));
9896a8d0d3d2 rust-node: handling binary Node prefix
Georges Racinet <georges.racinet@octobus.net>
parents: 44228
diff changeset
394 assert!(!NodePrefix::from_hex("12d")?.borrow().is_prefix_of(&node));
9896a8d0d3d2 rust-node: handling binary Node prefix
Georges Racinet <georges.racinet@octobus.net>
parents: 44228
diff changeset
395 Ok(())
9896a8d0d3d2 rust-node: handling binary Node prefix
Georges Racinet <georges.racinet@octobus.net>
parents: 44228
diff changeset
396 }
9896a8d0d3d2 rust-node: handling binary Node prefix
Georges Racinet <georges.racinet@octobus.net>
parents: 44228
diff changeset
397
9896a8d0d3d2 rust-node: handling binary Node prefix
Georges Racinet <georges.racinet@octobus.net>
parents: 44228
diff changeset
398 #[test]
9896a8d0d3d2 rust-node: handling binary Node prefix
Georges Racinet <georges.racinet@octobus.net>
parents: 44228
diff changeset
399 fn test_get_nybble() -> Result<(), NodeError> {
9896a8d0d3d2 rust-node: handling binary Node prefix
Georges Racinet <georges.racinet@octobus.net>
parents: 44228
diff changeset
400 let prefix = NodePrefix::from_hex("dead6789cafe")?;
9896a8d0d3d2 rust-node: handling binary Node prefix
Georges Racinet <georges.racinet@octobus.net>
parents: 44228
diff changeset
401 assert_eq!(prefix.borrow().get_nybble(0), 13);
9896a8d0d3d2 rust-node: handling binary Node prefix
Georges Racinet <georges.racinet@octobus.net>
parents: 44228
diff changeset
402 assert_eq!(prefix.borrow().get_nybble(7), 9);
9896a8d0d3d2 rust-node: handling binary Node prefix
Georges Racinet <georges.racinet@octobus.net>
parents: 44228
diff changeset
403 Ok(())
9896a8d0d3d2 rust-node: handling binary Node prefix
Georges Racinet <georges.racinet@octobus.net>
parents: 44228
diff changeset
404 }
44419
5ac1eecc9c64 rust-nodemap: core implementation for shortest
Georges Racinet <georges.racinet@octobus.net>
parents: 44262
diff changeset
405
5ac1eecc9c64 rust-nodemap: core implementation for shortest
Georges Racinet <georges.racinet@octobus.net>
parents: 44262
diff changeset
406 #[test]
5ac1eecc9c64 rust-nodemap: core implementation for shortest
Georges Racinet <georges.racinet@octobus.net>
parents: 44262
diff changeset
407 fn test_first_different_nybble_even_prefix() {
5ac1eecc9c64 rust-nodemap: core implementation for shortest
Georges Racinet <georges.racinet@octobus.net>
parents: 44262
diff changeset
408 let prefix = NodePrefix::from_hex("12ca").unwrap();
5ac1eecc9c64 rust-nodemap: core implementation for shortest
Georges Racinet <georges.racinet@octobus.net>
parents: 44262
diff changeset
409 let prefref = prefix.borrow();
5ac1eecc9c64 rust-nodemap: core implementation for shortest
Georges Racinet <georges.racinet@octobus.net>
parents: 44262
diff changeset
410 let mut node = Node::from([0; NODE_BYTES_LENGTH]);
5ac1eecc9c64 rust-nodemap: core implementation for shortest
Georges Racinet <georges.racinet@octobus.net>
parents: 44262
diff changeset
411 assert_eq!(prefref.first_different_nybble(&node), Some(0));
5ac1eecc9c64 rust-nodemap: core implementation for shortest
Georges Racinet <georges.racinet@octobus.net>
parents: 44262
diff changeset
412 node.data[0] = 0x13;
5ac1eecc9c64 rust-nodemap: core implementation for shortest
Georges Racinet <georges.racinet@octobus.net>
parents: 44262
diff changeset
413 assert_eq!(prefref.first_different_nybble(&node), Some(1));
5ac1eecc9c64 rust-nodemap: core implementation for shortest
Georges Racinet <georges.racinet@octobus.net>
parents: 44262
diff changeset
414 node.data[0] = 0x12;
5ac1eecc9c64 rust-nodemap: core implementation for shortest
Georges Racinet <georges.racinet@octobus.net>
parents: 44262
diff changeset
415 assert_eq!(prefref.first_different_nybble(&node), Some(2));
5ac1eecc9c64 rust-nodemap: core implementation for shortest
Georges Racinet <georges.racinet@octobus.net>
parents: 44262
diff changeset
416 node.data[1] = 0xca;
5ac1eecc9c64 rust-nodemap: core implementation for shortest
Georges Racinet <georges.racinet@octobus.net>
parents: 44262
diff changeset
417 // now it is a prefix
5ac1eecc9c64 rust-nodemap: core implementation for shortest
Georges Racinet <georges.racinet@octobus.net>
parents: 44262
diff changeset
418 assert_eq!(prefref.first_different_nybble(&node), None);
5ac1eecc9c64 rust-nodemap: core implementation for shortest
Georges Racinet <georges.racinet@octobus.net>
parents: 44262
diff changeset
419 }
5ac1eecc9c64 rust-nodemap: core implementation for shortest
Georges Racinet <georges.racinet@octobus.net>
parents: 44262
diff changeset
420
5ac1eecc9c64 rust-nodemap: core implementation for shortest
Georges Racinet <georges.racinet@octobus.net>
parents: 44262
diff changeset
421 #[test]
5ac1eecc9c64 rust-nodemap: core implementation for shortest
Georges Racinet <georges.racinet@octobus.net>
parents: 44262
diff changeset
422 fn test_first_different_nybble_odd_prefix() {
5ac1eecc9c64 rust-nodemap: core implementation for shortest
Georges Racinet <georges.racinet@octobus.net>
parents: 44262
diff changeset
423 let prefix = NodePrefix::from_hex("12c").unwrap();
5ac1eecc9c64 rust-nodemap: core implementation for shortest
Georges Racinet <georges.racinet@octobus.net>
parents: 44262
diff changeset
424 let prefref = prefix.borrow();
5ac1eecc9c64 rust-nodemap: core implementation for shortest
Georges Racinet <georges.racinet@octobus.net>
parents: 44262
diff changeset
425 let mut node = Node::from([0; NODE_BYTES_LENGTH]);
5ac1eecc9c64 rust-nodemap: core implementation for shortest
Georges Racinet <georges.racinet@octobus.net>
parents: 44262
diff changeset
426 assert_eq!(prefref.first_different_nybble(&node), Some(0));
5ac1eecc9c64 rust-nodemap: core implementation for shortest
Georges Racinet <georges.racinet@octobus.net>
parents: 44262
diff changeset
427 node.data[0] = 0x13;
5ac1eecc9c64 rust-nodemap: core implementation for shortest
Georges Racinet <georges.racinet@octobus.net>
parents: 44262
diff changeset
428 assert_eq!(prefref.first_different_nybble(&node), Some(1));
5ac1eecc9c64 rust-nodemap: core implementation for shortest
Georges Racinet <georges.racinet@octobus.net>
parents: 44262
diff changeset
429 node.data[0] = 0x12;
5ac1eecc9c64 rust-nodemap: core implementation for shortest
Georges Racinet <georges.racinet@octobus.net>
parents: 44262
diff changeset
430 assert_eq!(prefref.first_different_nybble(&node), Some(2));
5ac1eecc9c64 rust-nodemap: core implementation for shortest
Georges Racinet <georges.racinet@octobus.net>
parents: 44262
diff changeset
431 node.data[1] = 0xca;
5ac1eecc9c64 rust-nodemap: core implementation for shortest
Georges Racinet <georges.racinet@octobus.net>
parents: 44262
diff changeset
432 // now it is a prefix
5ac1eecc9c64 rust-nodemap: core implementation for shortest
Georges Racinet <georges.racinet@octobus.net>
parents: 44262
diff changeset
433 assert_eq!(prefref.first_different_nybble(&node), None);
5ac1eecc9c64 rust-nodemap: core implementation for shortest
Georges Racinet <georges.racinet@octobus.net>
parents: 44262
diff changeset
434 }
44228
7f86426fdd2c rust-node: binary Node ID and conversion utilities
Georges Racinet <georges.racinet@octobus.net>
parents:
diff changeset
435 }
44258
e52401a95b94 rust-nodemap: NodeMap trait with simplest implementation
Georges Racinet <georges.racinet@octobus.net>
parents: 44257
diff changeset
436
e52401a95b94 rust-nodemap: NodeMap trait with simplest implementation
Georges Racinet <georges.racinet@octobus.net>
parents: 44257
diff changeset
437 #[cfg(test)]
e52401a95b94 rust-nodemap: NodeMap trait with simplest implementation
Georges Racinet <georges.racinet@octobus.net>
parents: 44257
diff changeset
438 pub use tests::hex_pad_right;