diff --git a/db.json b/db.json
index 2c86c3c7..e06c5159 100644
--- a/db.json
+++ b/db.json
@@ -1 +1 @@
-{"meta":{"version":1,"warehouse":"4.0.2"},"models":{"Asset":[{"_id":"node_modules/hexo-theme-landscape/source/fancybox/jquery.fancybox.min.css","path":"fancybox/jquery.fancybox.min.css","modified":1,"renderable":1},{"_id":"node_modules/hexo-theme-landscape/source/js/jquery-3.4.1.min.js","path":"js/jquery-3.4.1.min.js","modified":1,"renderable":1},{"_id":"node_modules/hexo-theme-landscape/source/js/script.js","path":"js/script.js","modified":1,"renderable":1},{"_id":"node_modules/hexo-theme-landscape/source/fancybox/jquery.fancybox.min.js","path":"fancybox/jquery.fancybox.min.js","modified":1,"renderable":1},{"_id":"node_modules/hexo-theme-landscape/source/css/style.styl","path":"css/style.styl","modified":1,"renderable":1},{"_id":"node_modules/hexo-theme-landscape/source/css/fonts/FontAwesome.otf","path":"css/fonts/FontAwesome.otf","modified":1,"renderable":1},{"_id":"node_modules/hexo-theme-landscape/source/css/fonts/fontawesome-webfont.eot","path":"css/fonts/fontawesome-webfont.eot","modified":1,"renderable":1},{"_id":"node_modules/hexo-theme-landscape/source/css/fonts/fontawesome-webfont.svg","path":"css/fonts/fontawesome-webfont.svg","modified":1,"renderable":1},{"_id":"node_modules/hexo-theme-landscape/source/css/fonts/fontawesome-webfont.ttf","path":"css/fonts/fontawesome-webfont.ttf","modified":1,"renderable":1},{"_id":"node_modules/hexo-theme-landscape/source/css/fonts/fontawesome-webfont.woff","path":"css/fonts/fontawesome-webfont.woff","modified":1,"renderable":1},{"_id":"node_modules/hexo-theme-landscape/source/css/fonts/fontawesome-webfont.woff2","path":"css/fonts/fontawesome-webfont.woff2","modified":1,"renderable":1},{"_id":"node_modules/hexo-theme-landscape/source/css/images/banner.jpg","path":"css/images/banner.jpg","modified":1,"renderable":1},{"_id":"source/2017-552.pdf","path":"2017-552.pdf","modified":1,"renderable":0},{"_id":"source/images/evm.drawio.google.png","path":"images/evm.drawio.google.png","modified":1,"renderable":0},{"_id":"source/images/evm.layout.png","path":"images/evm.layout.png","modified":1,"renderable":0},{"_id":"source/images/geth_starts.drawio.png","path":"images/geth_starts.drawio.png","modified":1,"renderable":0},{"_id":"source/images/kademlia.locating.png","path":"images/kademlia.locating.png","modified":1,"renderable":0},{"_id":"source/images/kademlia.onlineprob.png","path":"images/kademlia.onlineprob.png","modified":1,"renderable":0},{"_id":"source/images/kademlia.subtree.png","path":"images/kademlia.subtree.png","modified":1,"renderable":0},{"_id":"source/images/mpt.png","path":"images/mpt.png","modified":1,"renderable":0},{"_id":"source/images/mpt.state.ref.png","path":"images/mpt.state.ref.png","modified":1,"renderable":0},{"_id":"source/images/trie.prefix.png","path":"images/trie.prefix.png","modified":1,"renderable":0},{"_id":"source/images/elliptic_curve/point_addition.webp","path":"images/elliptic_curve/point_addition.webp","modified":1,"renderable":0},{"_id":"source/images/geth/sync.mode.jpg","path":"images/geth/sync.mode.jpg","modified":1,"renderable":0},{"_id":"source/images/paillier/carmichael_thorem.png","path":"images/paillier/carmichael_thorem.png","modified":1,"renderable":0},{"_id":"source/images/paillier/carmichael_thorem_2.png","path":"images/paillier/carmichael_thorem_2.png","modified":1,"renderable":0},{"_id":"source/images/paillier/homomorphic_addition.png","path":"images/paillier/homomorphic_addition.png","modified":1,"renderable":0},{"_id":"source/images/paillier/homomorphic_mul.png","path":"images/paillier/homomorphic_mul.png","modified":1,"renderable":0},{"_id":"source/images/two_party_ecdsa/paillier_enc.png","path":"images/two_party_ecdsa/paillier_enc.png","modified":1,"renderable":0},{"_id":"source/images/two_party_ecdsa/schnorr_ecdsa_comparison.png","path":"images/two_party_ecdsa/schnorr_ecdsa_comparison.png","modified":1,"renderable":0},{"_id":"source/images/rust/macros/16.compile_process.png","path":"images/rust/macros/16.compile_process.png","modified":1,"renderable":0},{"_id":"source/images/rust/memory/trait_object_memory.png","path":"images/rust/memory/trait_object_memory.png","modified":1,"renderable":0},{"_id":"source/images/rust/ownership/move-string-2.png","path":"images/rust/ownership/move-string-2.png","modified":1,"renderable":0},{"_id":"source/images/rust/ownership/move-string.png","path":"images/rust/ownership/move-string.png","modified":1,"renderable":0},{"_id":"source/images/rust/pointers/cycle.ref.png","path":"images/rust/pointers/cycle.ref.png","modified":1,"renderable":0},{"_id":"source/images/rust/pointers/rc.png","path":"images/rust/pointers/rc.png","modified":1,"renderable":0}],"Cache":[{"_id":"source/images/evm.layout.png","hash":"6927cb3b922b2bcec926ec5d797e7ea8ea2b5d00","modified":1681440784560},{"_id":"source/images/kademlia.onlineprob.png","hash":"98c55aa819ef7047b3749c89eb4546f0d799a239","modified":1681443973575},{"_id":"source/_posts/blockchain.kademlia.md","hash":"0cb0522a114bc53d79f2db4a1bf2a02c29ef1c2f","modified":1681457596860},{"_id":"source/_posts/MPT.md","hash":"1d0394f11c3361b4474dbe49ced5c5751144fe91","modified":1681534320319},{"_id":"source/images/mpt.state.ref.png","hash":"ec747cf092820c0ab5f72d0f4f07f7705bb9ecf0","modified":1681533561017},{"_id":"source/images/elliptic_curve/point_addition.webp","hash":"ba6cd29aec4a694b53933d0824df180158f98316","modified":1689255155658},{"_id":"source/_posts/geth-fine-tune.md","hash":"5431cd654f7152fd5c590891a53568f54eec4125","modified":1682416094119},{"_id":"source/_posts/eth-sign.md","hash":"76a6376a62544d68438fb1759be07242a3e8e9ef","modified":1669607550181},{"_id":"source/images/geth/sync.mode.jpg","hash":"657cc148abc14f01e7483265c67936e73f79d0e4","modified":1687272599480},{"_id":"source/_posts/hello-world.md","hash":"8241e671f980a667f875b9a6493f17bd333a1cfb","modified":1680799419107},{"_id":"source/images/two_party_ecdsa/paillier_enc.png","hash":"132cdc74eb588951d1bd347b1b6e825912bc0460","modified":1682232953667},{"_id":"source/images/paillier/homomorphic_mul.png","hash":"e8a2420501140a8d48db202065aa221df92f19dc","modified":1682317735470},{"_id":"source/images/paillier/homomorphic_addition.png","hash":"26b0e4a070a7e29710e2ceace09bbdb79b3a883e","modified":1682317632123},{"_id":"source/_posts/golang/go-reflect.md","hash":"c2808bbd3bf422ab5679c246444975107b98fb1e","modified":1687070564968},{"_id":"source/_posts/rust/rust-01-resource.md","hash":"5e2c159128ccef35da0d3a2a72b6bb7e1c12fc73","modified":1688011565747},{"_id":"source/_posts/golang/go-similar-concepts-comparison.md","hash":"5de26ef1a5907db4264ff5e491b75aa2dfb43af1","modified":1687072042116},{"_id":"source/_posts/rust/rust-02-basics.md","hash":"be1111d868417c54b8b019938b8144e8be35df1f","modified":1682932033124},{"_id":"source/_posts/rust/rust-04-lifetime.md","hash":"d338498d7d159a3f94687082a10fc28ada706b16","modified":1682950129387},{"_id":"source/_posts/rust/rust-03-ownership.md","hash":"7d39498532088f438d76f1d0b42892bc985c0c95","modified":1682947052602},{"_id":"source/_posts/rust/rust-05-memory-layout.md","hash":"9a8c7dac3a23bca5f7692a3f6c0c8827dfd8c7e5","modified":1683082672719},{"_id":"source/_posts/rust/rust-07-macro.md","hash":"f6e51943ab413f5462baca1327c53ac20a8afcda","modified":1682950710350},{"_id":"source/_posts/rust/rust-06-smart-pointer.md","hash":"909ecf0ecf594651191e0953eca17aca7fa64669","modified":1683099103613},{"_id":"source/_posts/rust/rust-08-project-management.md","hash":"2c1ab1e7b8c8510935a694e33aa2c676437f0fd1","modified":1683099708892},{"_id":"source/_posts/rust/rust-async.md","hash":"f8b896f06752fcdb3c9fa34d2ed0ba958aef9c49","modified":1683106393753},{"_id":"source/_posts/rust/rust-10-concurrency.md","hash":"5bba6d7c1b0e3a24f07a4899f1162a93af8ad5b1","modified":1688283743897},{"_id":"source/_posts/rust/rust-09-functional.md","hash":"b2e1f9a46e02c5aa49ea19394e074777558a51eb","modified":1688003621688},{"_id":"source/_posts/rust/rust-cargo-doc.md","hash":"52303be5d9e342444a4cb661fa418ab68b28d640","modified":1683106131353},{"_id":"source/_posts/cryptography/cryptography-01-primitive-group-and-field.md","hash":"b109aef9a3c4ca55a7198c284cd007716b094044","modified":1689264071422},{"_id":"source/_posts/rust/rust-similar-concepts-comparison.md","hash":"17c7d67efd6315828a09762c633e7f8a0c9cdee2","modified":1688891607383},{"_id":"source/_posts/rust/rust-cargo-all-in-one.md","hash":"27eb587fe52f0461e1e30ed82b5d10a806e168f0","modified":1683108258682},{"_id":"source/_posts/rust/rust-sugar.md","hash":"dfa5a3f7bfd985118b97ae9055da496778b604e8","modified":1689060987147},{"_id":"source/_posts/cryptography/cryptography-03-rsa.md","hash":"00fd5cb12a4173ad1364e1c9d159fcf97e4040ad","modified":1689267250773},{"_id":"source/_posts/cryptography/cryptography-02-elliptic-curve.md","hash":"d3ef54a27b20eb8cc8db62c2fbfe632729b4c291","modified":1689264075193},{"_id":"source/_posts/rust/rust-tools.md","hash":"3019a116f156d05a95fd8fc76fa8b1380f778f24","modified":1683105904042},{"_id":"source/_posts/cryptography/paillier-encryption.md","hash":"4e43aa2d126bcb334563262563071c764c3ae19f","modified":1682317904177},{"_id":"source/_posts/cryptography/two-party-ecdsa.md","hash":"e94506f2f21233958c8f48184fad671919f32f8b","modified":1682317913595},{"_id":"source/_posts/zkp/zkp-a-brief-understanding.md","hash":"2e0f55f389b56b49dea2418cf062722ca339a0ea","modified":1689173902472},{"_id":"source/images/rust/memory/trait_object_memory.png","hash":"dd750cffa7bca5bde7856cfb65f4500de286c96f","modified":1683082638012},{"_id":"source/images/rust/ownership/move-string.png","hash":"d708edd6fb84b9d4ebe75556932f6b920934ca9a","modified":1682934539699},{"_id":"source/images/rust/pointers/rc.png","hash":"f568f69808ef0357ea5e6d42667d863b1139cbf1","modified":1683085079705},{"_id":"source/_posts/geth/tech_docs/geth.v1.10.0.md","hash":"d303922d31b987d5b57080fb6833b84e568de342","modified":1687100789245},{"_id":"source/_posts/geth/tech_docs/geth.prune.md","hash":"9ab8f315c3374f67ff7ac6f74a7fbef0ca9f7894","modified":1687341103628},{"_id":"source/_posts/geth/tech_docs/geth.sync.mode.md","hash":"7502b826b5ecbdd02f759a1780528dae344ccad7","modified":1687309420833},{"_id":"source/_posts/rust/crates/rust-serde.md","hash":"9b985750a751a7bd28effe9e97147e4207a5f093","modified":1688053726930},{"_id":"source/_posts/rust/crates/rust-frequently-used-crates.md","hash":"39aec8a77f62d6c3b164ecef0663a612423afd63","modified":1683106159269},{"_id":"source/_posts/rust/rust_std/rust-std-data-structure-1.md","hash":"34627ff9cff48a6a79a36d4e88cc4d32e118c3ae","modified":1689070720048},{"_id":"source/_posts/rust/rust_std/rust-smart-pointer-and-internal-mutibility.md","hash":"d97435f2c35ffcd4feb8a1aff787c7c20922438a","modified":1688915715385},{"_id":"source/_posts/geth/code_analysis/geth.1.rpc.md","hash":"623aec4f3cd8afb85b7b30d8bfde50bb2e5a4d4a","modified":1682614464069},{"_id":"source/_posts/rust/rust_std/rust-std-data-structure-2.md","hash":"32b80b9540433ffa77a3a7969e06921eb9ddbbca","modified":1688564475719},{"_id":"source/_posts/rust/rust_std/rust-std-sync.md","hash":"bf648427835ab0d834b2701b28bdfd35088aeb2e","modified":1688566866619},{"_id":"source/_posts/geth/code_analysis/geth.evm.md","hash":"ecea3e42003911dd58a2d6a9b8293f02ccb16a75","modified":1681441326144},{"_id":"source/_posts/geth/code_analysis/geth.0.get.start.md","hash":"6cd5256bae5e43f3dfcd341e27c52eccf8848f60","modified":1682434784499},{"_id":"source/images/evm.drawio.google.png","hash":"413a44d66153c93e2c31172d988e051a2bed9940","modified":1681436195264},{"_id":"source/images/geth_starts.drawio.png","hash":"3c426bd608121669f232aaa1b05ed7a342287fc8","modified":1682005494018},{"_id":"source/images/kademlia.subtree.png","hash":"d3198467460972151f4b2fe2b56fab0dd9e411ca","modified":1681442854122},{"_id":"source/images/trie.prefix.png","hash":"67d26d416faf0cc43ee35b4acda598e88dad2949","modified":1681520956971},{"_id":"source/images/paillier/carmichael_thorem.png","hash":"75b4d32eb2233db653bca52cdea4a624555b5ce4","modified":1682316092261},{"_id":"source/images/paillier/carmichael_thorem_2.png","hash":"29b103c94c36f4520ca8b675486af3d914998ac1","modified":1682316415073},{"_id":"source/images/two_party_ecdsa/schnorr_ecdsa_comparison.png","hash":"69cbed302af467a4e99653dfb51dca45c4a5a6f3","modified":1682231680569},{"_id":"source/images/rust/ownership/move-string-2.png","hash":"83342aed7ee254c099ada5d49ed8b9ba52a451a0","modified":1682934544128},{"_id":"source/images/rust/pointers/cycle.ref.png","hash":"ed99e2c6020833ccd5af751cf6eb2031cf47d9aa","modified":1683098263386},{"_id":"source/images/kademlia.locating.png","hash":"702d6b779294a3c6e033cc9bde14ef8950982310","modified":1681455579355},{"_id":"source/images/rust/macros/16.compile_process.png","hash":"444080319ca2101672941346988f78ed9a37c32d","modified":1682908885234},{"_id":"source/images/mpt.png","hash":"700032035bdcd793f94da522330552727b00e5a3","modified":1681533347412},{"_id":"node_modules/hexo-theme-landscape/package.json","hash":"9a94875cbf4c27fbe2e63da0496242addc6d2876","modified":1669606834570},{"_id":"node_modules/hexo-theme-landscape/LICENSE","hash":"c480fce396b23997ee23cc535518ffaaf7f458f8","modified":1669606834570},{"_id":"node_modules/hexo-theme-landscape/README.md","hash":"d2772ece6d4422ccdaa0359c3e07588834044052","modified":1669606834570},{"_id":"node_modules/hexo-theme-landscape/_config.yml","hash":"b608c1f1322760dce9805285a602a95832730a2e","modified":1669606834570},{"_id":"node_modules/hexo-theme-landscape/languages/de.yml","hash":"3ebf0775abbee928c8d7bda943c191d166ded0d3","modified":1669606834570},{"_id":"node_modules/hexo-theme-landscape/languages/en.yml","hash":"3083f319b352d21d80fc5e20113ddf27889c9d11","modified":1669606834570},{"_id":"node_modules/hexo-theme-landscape/languages/es.yml","hash":"76edb1171b86532ef12cfd15f5f2c1ac3949f061","modified":1669606834570},{"_id":"node_modules/hexo-theme-landscape/languages/fr.yml","hash":"415e1c580ced8e4ce20b3b0aeedc3610341c76fb","modified":1669606834570},{"_id":"node_modules/hexo-theme-landscape/languages/hu.yml","hash":"284d557130bf54a74e7dcef9d42096130e4d9550","modified":1669606834570},{"_id":"node_modules/hexo-theme-landscape/languages/it.yml","hash":"89b7d91306b2c1a0f3ac023b657bf974f798a1e8","modified":1669606834570},{"_id":"node_modules/hexo-theme-landscape/languages/ja.yml","hash":"a73e1b9c80fd6e930e2628b393bfe3fb716a21a9","modified":1669606834570},{"_id":"node_modules/hexo-theme-landscape/languages/pt.yml","hash":"57d07b75d434fbfc33b0ddb543021cb5f53318a8","modified":1669606834570},{"_id":"node_modules/hexo-theme-landscape/languages/mn.yml","hash":"2e7523951072a9403ead3840ad823edd1084c116","modified":1669606834570},{"_id":"node_modules/hexo-theme-landscape/languages/no.yml","hash":"965a171e70347215ec726952e63f5b47930931ef","modified":1669606834570},{"_id":"node_modules/hexo-theme-landscape/languages/ko.yml","hash":"881d6a0a101706e0452af81c580218e0bfddd9cf","modified":1669606834570},{"_id":"node_modules/hexo-theme-landscape/languages/zh-CN.yml","hash":"1efd95774f401c80193eac6ee3f1794bfe93dc5a","modified":1669606834570},{"_id":"node_modules/hexo-theme-landscape/languages/ru.yml","hash":"4fda301bbd8b39f2c714e2c934eccc4b27c0a2b0","modified":1669606834570},{"_id":"node_modules/hexo-theme-landscape/languages/nl.yml","hash":"12ed59faba1fc4e8cdd1d42ab55ef518dde8039c","modified":1669606834570},{"_id":"node_modules/hexo-theme-landscape/layout/category.ejs","hash":"765426a9c8236828dc34759e604cc2c52292835a","modified":1669606834570},{"_id":"node_modules/hexo-theme-landscape/layout/archive.ejs","hash":"2703b07cc8ac64ae46d1d263f4653013c7e1666b","modified":1669606834570},{"_id":"node_modules/hexo-theme-landscape/languages/tr.yml","hash":"a1cdbfa17682d7a971de8ab8588bf57c74224b5b","modified":1669606834570},{"_id":"node_modules/hexo-theme-landscape/layout/index.ejs","hash":"aa1b4456907bdb43e629be3931547e2d29ac58c8","modified":1669606834570},{"_id":"node_modules/hexo-theme-landscape/languages/zh-TW.yml","hash":"53ce3000c5f767759c7d2c4efcaa9049788599c3","modified":1669606834570},{"_id":"node_modules/hexo-theme-landscape/layout/page.ejs","hash":"7d80e4e36b14d30a7cd2ac1f61376d9ebf264e8b","modified":1669606834570},{"_id":"node_modules/hexo-theme-landscape/layout/layout.ejs","hash":"0d1765036e4874500e68256fedb7470e96eeb6ee","modified":1669606834570},{"_id":"node_modules/hexo-theme-landscape/scripts/fancybox.js","hash":"c857d7a5e4a5d71c743a009c5932bf84229db428","modified":1669606834570},{"_id":"node_modules/hexo-theme-landscape/layout/tag.ejs","hash":"eaa7b4ccb2ca7befb90142e4e68995fb1ea68b2e","modified":1669606834570},{"_id":"node_modules/hexo-theme-landscape/layout/post.ejs","hash":"7d80e4e36b14d30a7cd2ac1f61376d9ebf264e8b","modified":1669606834570},{"_id":"node_modules/hexo-theme-landscape/layout/_partial/after-footer.ejs","hash":"414914ebb159fac1922b056b905e570ac7521925","modified":1669606834570},{"_id":"node_modules/hexo-theme-landscape/layout/_partial/archive-post.ejs","hash":"c7a71425a946d05414c069ec91811b5c09a92c47","modified":1669606834570},{"_id":"node_modules/hexo-theme-landscape/layout/_partial/archive.ejs","hash":"7cb70a7a54f8c7ae49b10d1f37c0a9b74eab8826","modified":1669606834570},{"_id":"node_modules/hexo-theme-landscape/layout/_partial/footer.ejs","hash":"3656eb692254346671abc03cb3ba1459829e0dce","modified":1669606834570},{"_id":"node_modules/hexo-theme-landscape/layout/_partial/article.ejs","hash":"dfd555c00e85ffc4207c88968d12b219c1f086ec","modified":1669606834570},{"_id":"node_modules/hexo-theme-landscape/layout/_partial/google-analytics.ejs","hash":"2ea7442ea1e1a8ab4e41e26c563f58413b59a3d0","modified":1669606834570},{"_id":"node_modules/hexo-theme-landscape/layout/_widget/archive.ejs","hash":"beb4a86fcc82a9bdda9289b59db5a1988918bec3","modified":1669606834570},{"_id":"node_modules/hexo-theme-landscape/layout/_partial/gauges-analytics.ejs","hash":"21a1e2a3907d1a3dad1cd0ab855fe6735f233c74","modified":1669606834570},{"_id":"node_modules/hexo-theme-landscape/layout/_partial/mobile-nav.ejs","hash":"e952a532dfc583930a666b9d4479c32d4a84b44e","modified":1669606834570},{"_id":"node_modules/hexo-theme-landscape/layout/_partial/head.ejs","hash":"f215d92a882247a7cc5ea80b241bedfcec0ea6ca","modified":1669606834570},{"_id":"node_modules/hexo-theme-landscape/layout/_partial/sidebar.ejs","hash":"930da35cc2d447a92e5ee8f835735e6fd2232469","modified":1669606834570},{"_id":"node_modules/hexo-theme-landscape/layout/_widget/tag.ejs","hash":"2de380865df9ab5f577f7d3bcadf44261eb5faae","modified":1669606834570},{"_id":"node_modules/hexo-theme-landscape/layout/_partial/header.ejs","hash":"c1acd247e14588cdf101a69460cb8319c18cd078","modified":1669606834570},{"_id":"node_modules/hexo-theme-landscape/layout/_widget/category.ejs","hash":"dd1e5af3c6af3f5d6c85dfd5ca1766faed6a0b05","modified":1669606834570},{"_id":"node_modules/hexo-theme-landscape/layout/_widget/recent_posts.ejs","hash":"60c4b012dcc656438ff59997e60367e5a21ab746","modified":1669606834570},{"_id":"node_modules/hexo-theme-landscape/layout/_widget/tagcloud.ejs","hash":"b4a2079101643f63993dcdb32925c9b071763b46","modified":1669606834570},{"_id":"node_modules/hexo-theme-landscape/source/js/script.js","hash":"998ed4c5b147e1299bf62beebf33514474f28112","modified":1669606834570},{"_id":"node_modules/hexo-theme-landscape/source/css/_variables.styl","hash":"581b0cbefdaa5f894922133989dd2d3bf71ded79","modified":1669606834570},{"_id":"node_modules/hexo-theme-landscape/source/css/style.styl","hash":"9c451e5efd72c5bb8b56e8c2b94be731e99db05b","modified":1669606834570},{"_id":"node_modules/hexo-theme-landscape/source/fancybox/jquery.fancybox.min.css","hash":"1be9b79be02a1cfc5d96c4a5e0feb8f472babd95","modified":1669606834570},{"_id":"node_modules/hexo-theme-landscape/source/css/_extend.styl","hash":"222fbe6d222531d61c1ef0f868c90f747b1c2ced","modified":1669606834570},{"_id":"node_modules/hexo-theme-landscape/layout/_partial/post/date.ejs","hash":"f1458584b679545830b75bef2526e2f3eb931045","modified":1669606834570},{"_id":"node_modules/hexo-theme-landscape/layout/_partial/post/gallery.ejs","hash":"3d9d81a3c693ff2378ef06ddb6810254e509de5b","modified":1669606834570},{"_id":"node_modules/hexo-theme-landscape/layout/_partial/post/nav.ejs","hash":"16a904de7bceccbb36b4267565f2215704db2880","modified":1669606834570},{"_id":"node_modules/hexo-theme-landscape/layout/_partial/post/tag.ejs","hash":"2fcb0bf9c8847a644167a27824c9bb19ac74dd14","modified":1669606834570},{"_id":"node_modules/hexo-theme-landscape/layout/_partial/post/title.ejs","hash":"4d7e62574ddf46de9b41605fe3140d77b5ddb26d","modified":1669606834570},{"_id":"node_modules/hexo-theme-landscape/source/css/_partial/archive.styl","hash":"db15f5677dc68f1730e82190bab69c24611ca292","modified":1669606834570},{"_id":"node_modules/hexo-theme-landscape/source/css/_partial/article.styl","hash":"80759482d07063c091e940f964a1cf6693d3d406","modified":1669606834570},{"_id":"node_modules/hexo-theme-landscape/source/css/_partial/footer.styl","hash":"e35a060b8512031048919709a8e7b1ec0e40bc1b","modified":1669606834570},{"_id":"node_modules/hexo-theme-landscape/source/css/_partial/comment.styl","hash":"79d280d8d203abb3bd933ca9b8e38c78ec684987","modified":1669606834570},{"_id":"node_modules/hexo-theme-landscape/layout/_partial/post/category.ejs","hash":"c6bcd0e04271ffca81da25bcff5adf3d46f02fc0","modified":1669606834570},{"_id":"node_modules/hexo-theme-landscape/source/css/_partial/header.styl","hash":"85ab11e082f4dd86dde72bed653d57ec5381f30c","modified":1669606834570},{"_id":"node_modules/hexo-theme-landscape/source/css/_partial/highlight.styl","hash":"bf4e7be1968dad495b04e83c95eac14c4d0ad7c0","modified":1669606834570},{"_id":"node_modules/hexo-theme-landscape/source/css/_partial/mobile.styl","hash":"a399cf9e1e1cec3e4269066e2948d7ae5854d745","modified":1669606834570},{"_id":"node_modules/hexo-theme-landscape/source/css/_partial/sidebar-aside.styl","hash":"890349df5145abf46ce7712010c89237900b3713","modified":1669606834570},{"_id":"node_modules/hexo-theme-landscape/source/css/_partial/sidebar.styl","hash":"404ec059dc674a48b9ab89cd83f258dec4dcb24d","modified":1669606834570},{"_id":"node_modules/hexo-theme-landscape/source/css/_partial/sidebar-bottom.styl","hash":"8fd4f30d319542babfd31f087ddbac550f000a8a","modified":1669606834570},{"_id":"node_modules/hexo-theme-landscape/source/css/_util/grid.styl","hash":"0bf55ee5d09f193e249083602ac5fcdb1e571aed","modified":1669606834570},{"_id":"node_modules/hexo-theme-landscape/source/css/_util/mixin.styl","hash":"44f32767d9fd3c1c08a60d91f181ee53c8f0dbb3","modified":1669606834570},{"_id":"node_modules/hexo-theme-landscape/source/fancybox/jquery.fancybox.min.js","hash":"6181412e73966696d08e1e5b1243a572d0f22ba6","modified":1669606834570},{"_id":"node_modules/hexo-theme-landscape/source/js/jquery-3.4.1.min.js","hash":"88523924351bac0b5d560fe0c5781e2556e7693d","modified":1669606834570},{"_id":"node_modules/hexo-theme-landscape/source/css/fonts/fontawesome-webfont.woff2","hash":"d6f48cba7d076fb6f2fd6ba993a75b9dc1ecbf0c","modified":1669606834570},{"_id":"node_modules/hexo-theme-landscape/source/css/fonts/fontawesome-webfont.woff","hash":"28b782240b3e76db824e12c02754a9731a167527","modified":1669606834570},{"_id":"node_modules/hexo-theme-landscape/source/css/fonts/fontawesome-webfont.eot","hash":"d980c2ce873dc43af460d4d572d441304499f400","modified":1669606834570},{"_id":"node_modules/hexo-theme-landscape/source/css/fonts/FontAwesome.otf","hash":"048707bc52ac4b6563aaa383bfe8660a0ddc908c","modified":1669606834570},{"_id":"node_modules/hexo-theme-landscape/source/css/fonts/fontawesome-webfont.ttf","hash":"13b1eab65a983c7a73bc7997c479d66943f7c6cb","modified":1669606834570},{"_id":"node_modules/hexo-theme-landscape/source/css/images/banner.jpg","hash":"f44aa591089fcb3ec79770a1e102fd3289a7c6a6","modified":1669606834570},{"_id":"node_modules/hexo-theme-landscape/source/css/fonts/fontawesome-webfont.svg","hash":"98a8aa5cf7d62c2eff5f07ede8d844b874ef06ed","modified":1669606834570},{"_id":"source/2017-552.pdf","hash":"b1a08857c1f6532f1fbb718c48a34fd48ea7da70","modified":1682236639612},{"_id":"public/2023/06/20/zkp/zkp-a-brief-understanding/index.html","hash":"2932d6f4e874456026b3ee856550c9ff41533dc1","modified":1689267302416},{"_id":"public/2023/06/17/cryptography/cryptography-03-rsa/index.html","hash":"1da046d8ea0bb8db506868ec1b165b5739e75f0d","modified":1689267302416},{"_id":"public/2023/06/10/cryptography/cryptography-02-elliptic-curve/index.html","hash":"2ebc1d33c8cfede924e6e841f6ce41f503ac6612","modified":1689267302416},{"_id":"public/2023/06/01/rust/rust-10-concurrency/index.html","hash":"4d0fa39cd6d7c76922c5f4b9a179c1701b279513","modified":1689267302416},{"_id":"public/2023/03/25/geth/tech_docs/geth.prune/index.html","hash":"30599e6334ac9779c1d1c1e063c6272d92a01d60","modified":1689267302416},{"_id":"public/2023/04/01/rust/crates/rust-serde/index.html","hash":"b6d8edf99edb4d82f32ba4fa38801437105ec323","modified":1689267302416},{"_id":"public/2023/04/11/rust/rust-09-functional/index.html","hash":"f59beb2a9ae7c3227c1e33d8ed51e90b00edac6c","modified":1689267302416},{"_id":"public/2023/03/05/golang/go-similar-concepts-comparison/index.html","hash":"7ef4625d43e210240df45cbb2eca79337da6a399","modified":1689267302416},{"_id":"public/2023/02/07/cryptography/two-party-ecdsa/index.html","hash":"8b207984b06790882610c780d4309853f28a3f71","modified":1689267302416},{"_id":"public/2023/01/22/MPT/index.html","hash":"24a154eafc38313aa5c07e5c32ba9d7200c267ad","modified":1689267302416},{"_id":"public/2023/01/01/geth-fine-tune/index.html","hash":"b15f261756039fb3f1fe3bdefc988da4e8300d49","modified":1689267302416},{"_id":"public/2022/12/13/rust/crates/rust-frequently-used-crates/index.html","hash":"97a126f4e0931cd1127e7ddd100d53db9a71082c","modified":1689267302416},{"_id":"public/2022/11/28/eth-sign/index.html","hash":"718b4103a7ccf6b8a33700d6efc51a476d4a70d2","modified":1689267302416},{"_id":"public/2022/11/27/hello-world/index.html","hash":"80ed788a3a3ad1f8926be8924849ae5f22c522fb","modified":1689267302416},{"_id":"public/2022/11/20/rust/rust-tools/index.html","hash":"8011dfeb47ba5e84e00e485ba1f59586b1f405c8","modified":1689267302416},{"_id":"public/2022/11/13/rust/rust-cargo-doc/index.html","hash":"19298b1d7c59513cda44e9ee0fe8c701f4f0d581","modified":1689267302416},{"_id":"public/2022/11/08/geth/code_analysis/geth.1.rpc/index.html","hash":"c9f4ef6eac7038be7fbe321c02d3c206150d19de","modified":1689267302416},{"_id":"public/2022/10/25/rust/rust-05-memory-layout/index.html","hash":"d083eae7c0f10616b944837daaba85b2ca8e63e3","modified":1689267302416},{"_id":"public/2022/09/27/rust/rust-01-resource/index.html","hash":"4a5ad9e72e0df364ed658735c63a0467b2e274b1","modified":1689267302416},{"_id":"public/archives/index.html","hash":"b26f6e0dd685861e45389b5ae789b489306f324d","modified":1689267302416},{"_id":"public/archives/page/2/index.html","hash":"13bf2a1171af57af2b910fa745e14dc94e1cc7ac","modified":1689267302416},{"_id":"public/archives/page/3/index.html","hash":"9c062822896543a5e2df0ffed5afbcaac1f19620","modified":1689267302416},{"_id":"public/archives/page/4/index.html","hash":"615d799dd9cdd6a89fcd1aa801044fea99d0f4e1","modified":1689267302416},{"_id":"public/archives/page/5/index.html","hash":"68088e06cebf1cd86edb2dcc3da4f0f3a79abeca","modified":1689267302416},{"_id":"public/archives/2022/index.html","hash":"e1b68ff1386b22f992ecb792512bce0c81471fda","modified":1689267302416},{"_id":"public/archives/2022/09/index.html","hash":"2d9dec992d9793d7faf92331ced7e2c0893fc628","modified":1689267302416},{"_id":"public/archives/2022/page/2/index.html","hash":"d3b4d22a0df7511c590065832bbdb83a27626412","modified":1689267302416},{"_id":"public/archives/2022/11/index.html","hash":"2d86c51cf036245c0444508ff9078d0ab3ae7b0c","modified":1689267302416},{"_id":"public/archives/2022/10/index.html","hash":"0db4f58ca82e62e5e41109bb3995989407ebee2f","modified":1689267302416},{"_id":"public/archives/2022/12/index.html","hash":"e8973cc3006651081b8165ca03c344353c121308","modified":1689267302416},{"_id":"public/archives/2023/index.html","hash":"bfcf7d875f1db873fffffb35bf469bf7faa04337","modified":1689267302416},{"_id":"public/archives/2023/page/2/index.html","hash":"3378570ac96475bba027ffe2b5bcd7085eab5f4f","modified":1689267302416},{"_id":"public/archives/2023/page/3/index.html","hash":"f690fc3bfd31262ed096434c3c5209acdb75a517","modified":1689267302416},{"_id":"public/archives/2023/01/index.html","hash":"f2e5aae467c44820380e4013062de6200af91713","modified":1689267302416},{"_id":"public/archives/2023/02/index.html","hash":"97350905e138f0a39165abb99dae5c6aa766ebd7","modified":1689267302416},{"_id":"public/archives/2023/03/index.html","hash":"710cd060c7669a22bc36e19914933c5cec1e4d52","modified":1689267302416},{"_id":"public/archives/2023/04/index.html","hash":"f94514e2a73ebcd34eb2de4dae42768391617754","modified":1689267302416},{"_id":"public/archives/2023/05/index.html","hash":"d02d80c39e5b2cd50ad3609a277107ebc3025cc8","modified":1689267302416},{"_id":"public/archives/2023/06/index.html","hash":"606db95140374582e47446353fd6af27593f545e","modified":1689267302416},{"_id":"public/tags/blockchain/index.html","hash":"bb3e39ada873831c70a9f7ae6562a8c2cd0f5268","modified":1689267302416},{"_id":"public/tags/geth/index.html","hash":"23f6e67c14ecb91130841423774e08d08ce5955a","modified":1689267302416},{"_id":"public/tags/golang/index.html","hash":"da06c8f9f2c5e476474ed0de2c2d9f300ee75316","modified":1689267302416},{"_id":"public/tags/rust/index.html","hash":"e3133a5841f411d290f211e2119a6e7feae5f1f9","modified":1689267302416},{"_id":"public/tags/cargo/index.html","hash":"5e4eb2773b0e9b130b8bfc1b357a4443c99a6515","modified":1689267302416},{"_id":"public/tags/cryptography/index.html","hash":"f5c48068d7d3aeacdb2a50411462a75d40876bd7","modified":1689267302416},{"_id":"public/tags/zkp/index.html","hash":"b4dcf0f3b03d19763f83e9b5d053060e3b20c1d2","modified":1689267302416},{"_id":"public/tags/rust/page/2/index.html","hash":"c8f0911a1188a3fd24c477c63d3445feca73fef8","modified":1689267302416},{"_id":"public/tags/mpc/index.html","hash":"c53ecbdeb3ed9e736201c022ee63955dd90a1d0c","modified":1689267302416},{"_id":"public/tags/ecdsa/index.html","hash":"2119718393b2a77da4f95d7080a42a1b75ce93f7","modified":1689267302416},{"_id":"public/tags/rust-crate/index.html","hash":"e35ebad0ea539f26f07bf04bbdae2cbd6d6c77d9","modified":1689267302416},{"_id":"public/tags/rust-std/index.html","hash":"cdafc1b79d3b3d019e565bccf8705b5af02db2a8","modified":1689267302416},{"_id":"public/2023/06/08/rust/rust_std/rust-std-sync/index.html","hash":"058e8990c4467d86c835419ecf78796ced310e80","modified":1689267302416},{"_id":"public/2023/06/03/rust/rust_std/rust-smart-pointer-and-internal-mutibility/index.html","hash":"735fbfd942cf3e9dad9150be1c5227d91f28a561","modified":1689267302416},{"_id":"public/2023/06/03/cryptography/cryptography-01-primitive-group-and-field/index.html","hash":"d20bc6151690c8b56348795e757507e446a91e78","modified":1689267302416},{"_id":"public/2023/05/02/rust/rust_std/rust-std-data-structure-2/index.html","hash":"9bcc9796d999beba7164f419acb6a80a0f6ca326","modified":1689267302416},{"_id":"public/2023/05/01/rust/rust_std/rust-std-data-structure-1/index.html","hash":"c5378f2f1c7b6d18c6452e2cef85eea7d9b05036","modified":1689267302416},{"_id":"public/2023/03/15/geth/tech_docs/geth.v1.10.0/index.html","hash":"9a722579070e4e75ff6b498f8eae59e7290940dc","modified":1689267302416},{"_id":"public/2023/03/18/geth/tech_docs/geth.sync.mode/index.html","hash":"92d962427bc5b8b15494734d442bd52b44f01c1a","modified":1689267302416},{"_id":"public/2023/02/23/cryptography/paillier-encryption/index.html","hash":"e54db8f7129c2ae6917ed1ad1e9b86c4886245ce","modified":1689267302416},{"_id":"public/2023/03/02/golang/go-reflect/index.html","hash":"ad570826baa973bd8e924f328a06c2a885b5de4b","modified":1689267302416},{"_id":"public/2023/01/15/blockchain.kademlia/index.html","hash":"d7a6b3242bfadf95bf2f23c494a95abf1fee89cc","modified":1689267302416},{"_id":"public/2023/01/13/rust/rust-async/index.html","hash":"fd9cf2ce0eb65104c85a35811ec9fcb415a89949","modified":1689267302416},{"_id":"public/2023/01/08/geth/code_analysis/geth.evm/index.html","hash":"40a3c03dd9e3e6998915d4c69b0cd73bb9435940","modified":1689267302416},{"_id":"public/2022/12/28/rust/rust-07-macro/index.html","hash":"b9295db63e6b933be9ae1cc3b6333ed7d0f8c8c6","modified":1689267302416},{"_id":"public/2022/12/06/rust/rust-cargo-all-in-one/index.html","hash":"54dd77b0147a3c6f5c921515576348e34598708a","modified":1689267302416},{"_id":"public/2022/11/23/rust/rust-similar-concepts-comparison/index.html","hash":"04d891c41303f8ab8697ab56037329a30a3eeb96","modified":1689267302416},{"_id":"public/2022/11/17/rust/rust-sugar/index.html","hash":"e43566fece3f22a33312abd5f74e8ae40e0e928c","modified":1689267302416},{"_id":"public/2022/11/01/geth/code_analysis/geth.0.get.start/index.html","hash":"295c2545973f3aef6ddaf3ccb6fd396827abc2d0","modified":1689267302416},{"_id":"public/2022/11/06/rust/rust-08-project-management/index.html","hash":"e12e0a4ac72beb800e2309b6914e43386d123fee","modified":1689267302416},{"_id":"public/2022/10/30/rust/rust-06-smart-pointer/index.html","hash":"96da636bb5aad209d09e7ce12feb4cf50ca68e6d","modified":1689267302416},{"_id":"public/2022/10/18/rust/rust-04-lifetime/index.html","hash":"0dba0b342c9ca2b5dae764aa85049d2f6d4ed032","modified":1689267302416},{"_id":"public/2022/10/11/rust/rust-03-ownership/index.html","hash":"ced074bffa6ad877ee9566d8f0ed6758f3a4fee8","modified":1689267302416},{"_id":"public/2022/10/04/rust/rust-02-basics/index.html","hash":"6055b1f52ccd9f9b2f70f804e993c4e02c78819f","modified":1689267302416},{"_id":"public/index.html","hash":"47873e579076107b0e1bba21d1726ba73467bba1","modified":1689267302416},{"_id":"public/page/2/index.html","hash":"af0d327142257142c89da14c929faea639f5d2bd","modified":1689267302416},{"_id":"public/page/5/index.html","hash":"73fe79c7012b1a8c7c1f3cf37d0b4402ec9f811a","modified":1689267302416},{"_id":"public/page/3/index.html","hash":"4c6007d265222266143cdaebe0b5527d6578b818","modified":1689267302416},{"_id":"public/page/4/index.html","hash":"07303887258ded22a41b87ee84b39b4f8ce5c886","modified":1689267302416},{"_id":"public/images/evm.layout.png","hash":"6927cb3b922b2bcec926ec5d797e7ea8ea2b5d00","modified":1689267302416},{"_id":"public/images/kademlia.onlineprob.png","hash":"98c55aa819ef7047b3749c89eb4546f0d799a239","modified":1689267302416},{"_id":"public/images/elliptic_curve/point_addition.webp","hash":"ba6cd29aec4a694b53933d0824df180158f98316","modified":1689267302416},{"_id":"public/images/mpt.state.ref.png","hash":"ec747cf092820c0ab5f72d0f4f07f7705bb9ecf0","modified":1689267302416},{"_id":"public/images/geth/sync.mode.jpg","hash":"657cc148abc14f01e7483265c67936e73f79d0e4","modified":1689267302416},{"_id":"public/images/paillier/homomorphic_addition.png","hash":"26b0e4a070a7e29710e2ceace09bbdb79b3a883e","modified":1689267302416},{"_id":"public/images/two_party_ecdsa/paillier_enc.png","hash":"132cdc74eb588951d1bd347b1b6e825912bc0460","modified":1689267302416},{"_id":"public/images/paillier/homomorphic_mul.png","hash":"e8a2420501140a8d48db202065aa221df92f19dc","modified":1689267302416},{"_id":"public/images/rust/memory/trait_object_memory.png","hash":"dd750cffa7bca5bde7856cfb65f4500de286c96f","modified":1689267302416},{"_id":"public/images/rust/ownership/move-string.png","hash":"d708edd6fb84b9d4ebe75556932f6b920934ca9a","modified":1689267302416},{"_id":"public/images/rust/pointers/rc.png","hash":"f568f69808ef0357ea5e6d42667d863b1139cbf1","modified":1689267302416},{"_id":"public/fancybox/jquery.fancybox.min.css","hash":"1be9b79be02a1cfc5d96c4a5e0feb8f472babd95","modified":1689267302416},{"_id":"public/js/script.js","hash":"998ed4c5b147e1299bf62beebf33514474f28112","modified":1689267302416},{"_id":"public/js/jquery-3.4.1.min.js","hash":"88523924351bac0b5d560fe0c5781e2556e7693d","modified":1689267302416},{"_id":"public/css/style.css","hash":"4da345d832a2682bcaee3ab3e22c15e3cd0e9cde","modified":1689267302416},{"_id":"public/fancybox/jquery.fancybox.min.js","hash":"6181412e73966696d08e1e5b1243a572d0f22ba6","modified":1689267302416},{"_id":"public/css/fonts/fontawesome-webfont.woff2","hash":"d6f48cba7d076fb6f2fd6ba993a75b9dc1ecbf0c","modified":1689267302416},{"_id":"public/images/geth_starts.drawio.png","hash":"3c426bd608121669f232aaa1b05ed7a342287fc8","modified":1689267302416},{"_id":"public/images/kademlia.subtree.png","hash":"d3198467460972151f4b2fe2b56fab0dd9e411ca","modified":1689267302416},{"_id":"public/css/fonts/fontawesome-webfont.woff","hash":"28b782240b3e76db824e12c02754a9731a167527","modified":1689267302416},{"_id":"public/images/trie.prefix.png","hash":"67d26d416faf0cc43ee35b4acda598e88dad2949","modified":1689267302416},{"_id":"public/images/paillier/carmichael_thorem.png","hash":"75b4d32eb2233db653bca52cdea4a624555b5ce4","modified":1689267302416},{"_id":"public/images/paillier/carmichael_thorem_2.png","hash":"29b103c94c36f4520ca8b675486af3d914998ac1","modified":1689267302416},{"_id":"public/images/evm.drawio.google.png","hash":"413a44d66153c93e2c31172d988e051a2bed9940","modified":1689267302416},{"_id":"public/images/two_party_ecdsa/schnorr_ecdsa_comparison.png","hash":"69cbed302af467a4e99653dfb51dca45c4a5a6f3","modified":1689267302416},{"_id":"public/images/rust/pointers/cycle.ref.png","hash":"ed99e2c6020833ccd5af751cf6eb2031cf47d9aa","modified":1689267302416},{"_id":"public/images/rust/ownership/move-string-2.png","hash":"83342aed7ee254c099ada5d49ed8b9ba52a451a0","modified":1689267302416},{"_id":"public/css/fonts/fontawesome-webfont.eot","hash":"d980c2ce873dc43af460d4d572d441304499f400","modified":1689267302416},{"_id":"public/css/fonts/FontAwesome.otf","hash":"048707bc52ac4b6563aaa383bfe8660a0ddc908c","modified":1689267302416},{"_id":"public/css/fonts/fontawesome-webfont.ttf","hash":"13b1eab65a983c7a73bc7997c479d66943f7c6cb","modified":1689267302416},{"_id":"public/css/images/banner.jpg","hash":"f44aa591089fcb3ec79770a1e102fd3289a7c6a6","modified":1689267302416},{"_id":"public/images/kademlia.locating.png","hash":"702d6b779294a3c6e033cc9bde14ef8950982310","modified":1689267302416},{"_id":"public/images/rust/macros/16.compile_process.png","hash":"444080319ca2101672941346988f78ed9a37c32d","modified":1689267302416},{"_id":"public/images/mpt.png","hash":"700032035bdcd793f94da522330552727b00e5a3","modified":1689267302416},{"_id":"public/css/fonts/fontawesome-webfont.svg","hash":"98a8aa5cf7d62c2eff5f07ede8d844b874ef06ed","modified":1689267302416},{"_id":"public/2017-552.pdf","hash":"b1a08857c1f6532f1fbb718c48a34fd48ea7da70","modified":1689267302416}],"Category":[],"Data":[],"Page":[],"Post":[{"title":"MPT","date":"2023-01-22T09:25:36.000Z","_content":"\n# trie\na trie, also called prefix tree, is a type of k-ary search tree. These keys are most often strings, with links between nodes defined not by the entire key, but by individual characters. In order to access a key, the trie is traversed depth-first, following the links between nodes, which represent each character in the key.\n\n![prefix trie](/images/trie.prefix.png)\nIn general, the nodes of a Trie look like this:\n```\n[ [Ia, Ib, … I*], value]\n```\n[Ia, Ib, ... I*] is the index array of the node, which takes the next character in the key as the index, and each element I* points to the corresponding child node. value represents the value\n\n# MPT\nEach block of Ethereum contains three MPT trees, respectively\n\n- Transaction tree\n- Receipt tree\n- State tree\n\nIn the figure below are two block headers, where state root, tx root receipt root stores the roots of the three trees, and the second block shows when the data of account 175 changes (27 -> 45). Only need to store 3 nodes related to this account, and the data in the old block can still be accessed normally. (This is somewhat similar to the implementation of an immutable data structure in a functional programming language.) The detailed structure is\n\n![state reference](/images/mpt.state.ref.png)\n\n- use []byte as key, other than string\n- nibble: the smallest unit of the key type (4 bit)\n- Use hashes to refer to nodes instead of memory pointers\n\nthere are two types of node: full nodes (fullNode) and short nodes (shortNode). Full nodes have 17 elements, while shortNode nodes have two elements. Their schematic expressions are as follows\n```\nfullNode: [i0, i1, i2, … i15, hash] \nshortNode: [ [k0, k1, … kn], hash ] // first element is an array\n```\nif the hash pointing to a value, it is a leaf node; if pointing another node, a non leaf node. shortNode contains extension and leaf node. full node is branch node.\n\n![mpt](/images/mpt.png)\n\nUse the upper 4 bits of the first byte of the []byte value composed of nibbles as storage flag. The 0th bit stores the parity information, and the 1st bit stores the type represented by the value\n|hex char| bits | pointing to | odd/even | 2nd niddle padding |\n| -----|:----:|:----:|:----:|-------|\n|0| 0000 | node | even | no |\n|1| 0001 | node | odd | yes |\n|2| 0010 | value | even | no |\n|3| 0011 | value | odd | yes |\n\nthis encoding method is only used when accessing the database. After reading into memory, the key is directly stored in []byte type\n\nIn the trie module, there is a `Database` object, which you can understand as a cache layer of the underlying database. In actual use, the Trie object uses the Database as a database. However, the important function of Database is not caching, but the reference counting of node data during caching, and provides Database.Reference and Database.Dereference to reference and dereference a trie node. If the reference count of a node becomes 0, the node will be deleted from memory, so it will not be written to the real database\n\n# reference\n- [github](https://github.com/agiletechvn/go-ethereum-code-analysis/blob/master/trie-analysis.md)\n- [yangzhe's blog](http://yangzhe.me/2019/01/12/ethereum-trie-part-1/)\n- [yangzhe's blod](http://yangzhe.me/2019/01/18/ethereum-trie-part-2/)","source":"_posts/MPT.md","raw":"---\ntitle: MPT\ndate: 2023-01-22 17:25:36\ntags: [blockchain, geth]\n---\n\n# trie\na trie, also called prefix tree, is a type of k-ary search tree. These keys are most often strings, with links between nodes defined not by the entire key, but by individual characters. In order to access a key, the trie is traversed depth-first, following the links between nodes, which represent each character in the key.\n\n![prefix trie](/images/trie.prefix.png)\nIn general, the nodes of a Trie look like this:\n```\n[ [Ia, Ib, … I*], value]\n```\n[Ia, Ib, ... I*] is the index array of the node, which takes the next character in the key as the index, and each element I* points to the corresponding child node. value represents the value\n\n# MPT\nEach block of Ethereum contains three MPT trees, respectively\n\n- Transaction tree\n- Receipt tree\n- State tree\n\nIn the figure below are two block headers, where state root, tx root receipt root stores the roots of the three trees, and the second block shows when the data of account 175 changes (27 -> 45). Only need to store 3 nodes related to this account, and the data in the old block can still be accessed normally. (This is somewhat similar to the implementation of an immutable data structure in a functional programming language.) The detailed structure is\n\n![state reference](/images/mpt.state.ref.png)\n\n- use []byte as key, other than string\n- nibble: the smallest unit of the key type (4 bit)\n- Use hashes to refer to nodes instead of memory pointers\n\nthere are two types of node: full nodes (fullNode) and short nodes (shortNode). Full nodes have 17 elements, while shortNode nodes have two elements. Their schematic expressions are as follows\n```\nfullNode: [i0, i1, i2, … i15, hash] \nshortNode: [ [k0, k1, … kn], hash ] // first element is an array\n```\nif the hash pointing to a value, it is a leaf node; if pointing another node, a non leaf node. shortNode contains extension and leaf node. full node is branch node.\n\n![mpt](/images/mpt.png)\n\nUse the upper 4 bits of the first byte of the []byte value composed of nibbles as storage flag. The 0th bit stores the parity information, and the 1st bit stores the type represented by the value\n|hex char| bits | pointing to | odd/even | 2nd niddle padding |\n| -----|:----:|:----:|:----:|-------|\n|0| 0000 | node | even | no |\n|1| 0001 | node | odd | yes |\n|2| 0010 | value | even | no |\n|3| 0011 | value | odd | yes |\n\nthis encoding method is only used when accessing the database. After reading into memory, the key is directly stored in []byte type\n\nIn the trie module, there is a `Database` object, which you can understand as a cache layer of the underlying database. In actual use, the Trie object uses the Database as a database. However, the important function of Database is not caching, but the reference counting of node data during caching, and provides Database.Reference and Database.Dereference to reference and dereference a trie node. If the reference count of a node becomes 0, the node will be deleted from memory, so it will not be written to the real database\n\n# reference\n- [github](https://github.com/agiletechvn/go-ethereum-code-analysis/blob/master/trie-analysis.md)\n- [yangzhe's blog](http://yangzhe.me/2019/01/12/ethereum-trie-part-1/)\n- [yangzhe's blod](http://yangzhe.me/2019/01/18/ethereum-trie-part-2/)","slug":"MPT","published":1,"updated":"2023-04-15T04:52:00.319Z","comments":1,"layout":"post","photos":[],"link":"","_id":"clk1e4wpi00006hsj5wv8brh1","content":"
trie
a trie, also called prefix tree, is a type of k-ary search tree. These keys are most often strings, with links between nodes defined not by the entire key, but by individual characters. In order to access a key, the trie is traversed depth-first, following the links between nodes, which represent each character in the key.
\n
In general, the nodes of a Trie look like this:
\n
1
[ [Ia, Ib, … I*], value]
\n
[Ia, Ib, … I*] is the index array of the node, which takes the next character in the key as the index, and each element I* points to the corresponding child node. value represents the value
\n
MPT
Each block of Ethereum contains three MPT trees, respectively
\n
\n
Transaction tree
\n
Receipt tree
\n
State tree
\n
\n
In the figure below are two block headers, where state root, tx root receipt root stores the roots of the three trees, and the second block shows when the data of account 175 changes (27 -> 45). Only need to store 3 nodes related to this account, and the data in the old block can still be accessed normally. (This is somewhat similar to the implementation of an immutable data structure in a functional programming language.) The detailed structure is
\n\n
\n
use []byte as key, other than string
\n
nibble: the smallest unit of the key type (4 bit)
\n
Use hashes to refer to nodes instead of memory pointers
\n
\n
there are two types of node: full nodes (fullNode) and short nodes (shortNode). Full nodes have 17 elements, while shortNode nodes have two elements. Their schematic expressions are as follows
\n
1 2
fullNode: [i0, i1, i2, … i15, hash] shortNode: [ [k0, k1, … kn], hash ] // first element is an array
\n
if the hash pointing to a value, it is a leaf node; if pointing another node, a non leaf node. shortNode contains extension and leaf node. full node is branch node.
\n\n
Use the upper 4 bits of the first byte of the []byte value composed of nibbles as storage flag. The 0th bit stores the parity information, and the 1st bit stores the type represented by the value
\n
\n\n
\n
hex char
\n
bits
\n
pointing to
\n
odd/even
\n
2nd niddle padding
\n
\n\n
\n
0
\n
0000
\n
node
\n
even
\n
no
\n
\n
\n
1
\n
0001
\n
node
\n
odd
\n
yes
\n
\n
\n
2
\n
0010
\n
value
\n
even
\n
no
\n
\n
\n
3
\n
0011
\n
value
\n
odd
\n
yes
\n
\n
\n
this encoding method is only used when accessing the database. After reading into memory, the key is directly stored in []byte type
\n
In the trie module, there is a Database object, which you can understand as a cache layer of the underlying database. In actual use, the Trie object uses the Database as a database. However, the important function of Database is not caching, but the reference counting of node data during caching, and provides Database.Reference and Database.Dereference to reference and dereference a trie node. If the reference count of a node becomes 0, the node will be deleted from memory, so it will not be written to the real database
a trie, also called prefix tree, is a type of k-ary search tree. These keys are most often strings, with links between nodes defined not by the entire key, but by individual characters. In order to access a key, the trie is traversed depth-first, following the links between nodes, which represent each character in the key.
\n
In general, the nodes of a Trie look like this:
\n
1
[ [Ia, Ib, … I*], value]
\n
[Ia, Ib, … I*] is the index array of the node, which takes the next character in the key as the index, and each element I* points to the corresponding child node. value represents the value
\n
MPT
Each block of Ethereum contains three MPT trees, respectively
\n
\n
Transaction tree
\n
Receipt tree
\n
State tree
\n
\n
In the figure below are two block headers, where state root, tx root receipt root stores the roots of the three trees, and the second block shows when the data of account 175 changes (27 -> 45). Only need to store 3 nodes related to this account, and the data in the old block can still be accessed normally. (This is somewhat similar to the implementation of an immutable data structure in a functional programming language.) The detailed structure is
\n\n
\n
use []byte as key, other than string
\n
nibble: the smallest unit of the key type (4 bit)
\n
Use hashes to refer to nodes instead of memory pointers
\n
\n
there are two types of node: full nodes (fullNode) and short nodes (shortNode). Full nodes have 17 elements, while shortNode nodes have two elements. Their schematic expressions are as follows
\n
1 2
fullNode: [i0, i1, i2, … i15, hash] shortNode: [ [k0, k1, … kn], hash ] // first element is an array
\n
if the hash pointing to a value, it is a leaf node; if pointing another node, a non leaf node. shortNode contains extension and leaf node. full node is branch node.
\n\n
Use the upper 4 bits of the first byte of the []byte value composed of nibbles as storage flag. The 0th bit stores the parity information, and the 1st bit stores the type represented by the value
\n
\n\n
\n
hex char
\n
bits
\n
pointing to
\n
odd/even
\n
2nd niddle padding
\n
\n\n
\n
0
\n
0000
\n
node
\n
even
\n
no
\n
\n
\n
1
\n
0001
\n
node
\n
odd
\n
yes
\n
\n
\n
2
\n
0010
\n
value
\n
even
\n
no
\n
\n
\n
3
\n
0011
\n
value
\n
odd
\n
yes
\n
\n
\n
this encoding method is only used when accessing the database. After reading into memory, the key is directly stored in []byte type
\n
In the trie module, there is a Database object, which you can understand as a cache layer of the underlying database. In actual use, the Trie object uses the Database as a database. However, the important function of Database is not caching, but the reference counting of node data during caching, and provides Database.Reference and Database.Dereference to reference and dereference a trie node. If the reference count of a node becomes 0, the node will be deleted from memory, so it will not be written to the real database
\n"},{"title":"understanding of kademlia protocol","date":"2023-01-15T03:00:30.000Z","_content":"\n# Introduction\nKademlia, a peer-to-peer distributed hash table(DHT). Some other DHT techniques are Chord. In the Kad network, each node has a unique 160-bit ID (ETH account address is 20 bytes, which is 160 bits) pairs are stored in nodes whose ID is 'close' to the key for some notion of closeness. \n\n# system description\nKad effectively treats nodes as leaves in a binary tree, with each nodes's position determined by the shortest unique prefix of its ID. Figure 1 shows the position of a node with unique prefix 0011 in an example.\n\n![Figure 1](/images/kademlia.subtree.png)\nfor any given node, the binary tree is divided into a series of successively lower subtrees that don't contain the node.\n The highest-level subtree is composed of the other half of the whole tree that does not contain itself; the next level of subtree is composed of the remaining half that does not contain itself; and so on, until the complete tree is split into n subtrees. As shown in the figure, the part contained by the dotted line is the subtree of node 0011.\n\nif there is at least one node knwon in each subtree (in total, at least n nodes), a recursive routing algorithm can be used to reach any node within the binary tree. Figure 2 shows an example of node 0011 locating node 1110 by successively querying the best node it knows of to find contacts in lower and lower subtrees; finaly the lookup converges to the target node.\n\n![Figure 2](/images/kademlia.locating.png)\n\n## node distance: XOR metric\nNode's id is 160 bit. Keys are also 160 bit. The Kad algorithm uses an XOR operation to calculate the distance between nodes.\nd(x,y) = x XOR y\n\n## node state\nfor each 0 <= i < 160, every node keeps k triples (as a list) for nodes of distance between 2^i and 2^i+1 from itself. it is called k-buckets.\neach k-bucket is kept sorted by time last seen--least recently seen node at the head, most-recently seen at the tail.\nfor small values of i, the k-buckets will generally be empty (as no approriate nodes will exist).\n\n The K value mentioned here is a system-level constant (must be an even number). It is set by the software system using Kad (for example, the Kad network used by BT download, K is set to 8). \n\n## update of k bucket\nThere are mainly the following ways to update the K bucket:\n\n- Actively collect nodes: Any node can initiate a FIND_NODE (query node) request to refresh the node information in the K-bucket.\n- Passive collection node: When receiving requests from other nodes (such as: FIND_NODE, FIND_VALUE), it will add the node ID of the other party to a certain K-bucket.\n- Detect invalid nodes: By initiating a PING request, determine whether a node in the K-bucket is online, and then clean up which offline nodes in the K-bucket.\n\nThe update principle is to insert the latest node into the tail of the queue, and not to remove the online nodes in the queue.\n\nAccording to the K-bucket update principle, nodes with a long online time are more likely to remain in the K-bucket list. Therefore, by keeping the nodes with a long online time in the K-bucket, Kad will significantly increase the number of nodes in the K-bucket. it can defend against DOS attacks to a certain extent, because only when the old node fails, Kad will update the K bucket information, which avoids flooding routing information through the addition of new nodes\n![probability of continuous online agains onlie duration](/images/kademlia.onlineprob.png)\n\n## RPC method\nThe Kademlia protocol includes four remote RPC operations: PING, STORE, FIND_NODE, FIND_VALUE.\n\n- PING probes a node to see if it is online.\n- STORE instructs a node to store a pair for later retrieval.\n- FIND_NODE takes a 160bit ID as an argument. The receiver of this operation returns the (IP address, UDP port, Node ID) information of K nodes that it knows are closer to the target ID. The information of these nodes can be obtained from a single K-bucket, or from multiple K-buckets. In either case, the receiver will return the information of K nodes to the operation initiator. \n- The FIND_VALUE operation is similar to the FIND_NODE operation, with one exception. if the RPC receipients has received a STORE RPC for the key, it just returns the stored value.\n\n## node lookup\nKad participant must locate the k closest nodes to some given node ID. Kad employs a recursive algorithm for node lookups. It recursively send FIND_NODE requests to \\alpha (out of k) closest nodes it knows of. \n\n## find a pair\nto find a pair, a node starts by performing a lookup to find the k nodes with IDs closest to the key. However, value lookups use FIND_VLAUE rather than FIND_NODE RPCs.\n\n## node join\nto join the network, a node u must have a contact to an already participating node w.\n\n## routing table\n\n# references\n- [kademlia paper](https://pdos.csail.mit.edu/~petar/papers/maymounkov-kademlia-lncs.pdf)\n- [go implementation](https://github.com/libp2p/go-libp2p-kad-dht)\n- [kademlia stanford](https://codethechange.stanford.edu/guides/guide_kademlia.html)\n- [zhihu](https://zhuanlan.zhihu.com/p/388994038)","source":"_posts/blockchain.kademlia.md","raw":"---\ntitle: understanding of kademlia protocol\ndate: 2023-01-15 11:00:30\ntags: [blockchain]\n---\n\n# Introduction\nKademlia, a peer-to-peer distributed hash table(DHT). Some other DHT techniques are Chord. In the Kad network, each node has a unique 160-bit ID (ETH account address is 20 bytes, which is 160 bits) pairs are stored in nodes whose ID is 'close' to the key for some notion of closeness. \n\n# system description\nKad effectively treats nodes as leaves in a binary tree, with each nodes's position determined by the shortest unique prefix of its ID. Figure 1 shows the position of a node with unique prefix 0011 in an example.\n\n![Figure 1](/images/kademlia.subtree.png)\nfor any given node, the binary tree is divided into a series of successively lower subtrees that don't contain the node.\n The highest-level subtree is composed of the other half of the whole tree that does not contain itself; the next level of subtree is composed of the remaining half that does not contain itself; and so on, until the complete tree is split into n subtrees. As shown in the figure, the part contained by the dotted line is the subtree of node 0011.\n\nif there is at least one node knwon in each subtree (in total, at least n nodes), a recursive routing algorithm can be used to reach any node within the binary tree. Figure 2 shows an example of node 0011 locating node 1110 by successively querying the best node it knows of to find contacts in lower and lower subtrees; finaly the lookup converges to the target node.\n\n![Figure 2](/images/kademlia.locating.png)\n\n## node distance: XOR metric\nNode's id is 160 bit. Keys are also 160 bit. The Kad algorithm uses an XOR operation to calculate the distance between nodes.\nd(x,y) = x XOR y\n\n## node state\nfor each 0 <= i < 160, every node keeps k triples (as a list) for nodes of distance between 2^i and 2^i+1 from itself. it is called k-buckets.\neach k-bucket is kept sorted by time last seen--least recently seen node at the head, most-recently seen at the tail.\nfor small values of i, the k-buckets will generally be empty (as no approriate nodes will exist).\n\n The K value mentioned here is a system-level constant (must be an even number). It is set by the software system using Kad (for example, the Kad network used by BT download, K is set to 8). \n\n## update of k bucket\nThere are mainly the following ways to update the K bucket:\n\n- Actively collect nodes: Any node can initiate a FIND_NODE (query node) request to refresh the node information in the K-bucket.\n- Passive collection node: When receiving requests from other nodes (such as: FIND_NODE, FIND_VALUE), it will add the node ID of the other party to a certain K-bucket.\n- Detect invalid nodes: By initiating a PING request, determine whether a node in the K-bucket is online, and then clean up which offline nodes in the K-bucket.\n\nThe update principle is to insert the latest node into the tail of the queue, and not to remove the online nodes in the queue.\n\nAccording to the K-bucket update principle, nodes with a long online time are more likely to remain in the K-bucket list. Therefore, by keeping the nodes with a long online time in the K-bucket, Kad will significantly increase the number of nodes in the K-bucket. it can defend against DOS attacks to a certain extent, because only when the old node fails, Kad will update the K bucket information, which avoids flooding routing information through the addition of new nodes\n![probability of continuous online agains onlie duration](/images/kademlia.onlineprob.png)\n\n## RPC method\nThe Kademlia protocol includes four remote RPC operations: PING, STORE, FIND_NODE, FIND_VALUE.\n\n- PING probes a node to see if it is online.\n- STORE instructs a node to store a pair for later retrieval.\n- FIND_NODE takes a 160bit ID as an argument. The receiver of this operation returns the (IP address, UDP port, Node ID) information of K nodes that it knows are closer to the target ID. The information of these nodes can be obtained from a single K-bucket, or from multiple K-buckets. In either case, the receiver will return the information of K nodes to the operation initiator. \n- The FIND_VALUE operation is similar to the FIND_NODE operation, with one exception. if the RPC receipients has received a STORE RPC for the key, it just returns the stored value.\n\n## node lookup\nKad participant must locate the k closest nodes to some given node ID. Kad employs a recursive algorithm for node lookups. It recursively send FIND_NODE requests to \\alpha (out of k) closest nodes it knows of. \n\n## find a pair\nto find a pair, a node starts by performing a lookup to find the k nodes with IDs closest to the key. However, value lookups use FIND_VLAUE rather than FIND_NODE RPCs.\n\n## node join\nto join the network, a node u must have a contact to an already participating node w.\n\n## routing table\n\n# references\n- [kademlia paper](https://pdos.csail.mit.edu/~petar/papers/maymounkov-kademlia-lncs.pdf)\n- [go implementation](https://github.com/libp2p/go-libp2p-kad-dht)\n- [kademlia stanford](https://codethechange.stanford.edu/guides/guide_kademlia.html)\n- [zhihu](https://zhuanlan.zhihu.com/p/388994038)","slug":"blockchain.kademlia","published":1,"updated":"2023-04-14T07:33:16.860Z","comments":1,"layout":"post","photos":[],"link":"","_id":"clk1e4wpl00016hsjdgw02i4v","content":"
Introduction
Kademlia, a peer-to-peer distributed hash table(DHT). Some other DHT techniques are Chord. In the Kad network, each node has a unique 160-bit ID (ETH account address is 20 bytes, which is 160 bits) <key,value> pairs are stored in nodes whose ID is ‘close’ to the key for some notion of closeness.
\n
system description
Kad effectively treats nodes as leaves in a binary tree, with each nodes’s position determined by the shortest unique prefix of its ID. Figure 1 shows the position of a node with unique prefix 0011 in an example.
\n
for any given node, the binary tree is divided into a series of successively lower subtrees that don’t contain the node. The highest-level subtree is composed of the other half of the whole tree that does not contain itself; the next level of subtree is composed of the remaining half that does not contain itself; and so on, until the complete tree is split into n subtrees. As shown in the figure, the part contained by the dotted line is the subtree of node 0011.
\n
if there is at least one node knwon in each subtree (in total, at least n nodes), a recursive routing algorithm can be used to reach any node within the binary tree. Figure 2 shows an example of node 0011 locating node 1110 by successively querying the best node it knows of to find contacts in lower and lower subtrees; finaly the lookup converges to the target node.
\n\n
node distance: XOR metric
Node’s id is 160 bit. Keys are also 160 bit. The Kad algorithm uses an XOR operation to calculate the distance between nodes. d(x,y) = x XOR y
\n
node state
for each 0 <= i < 160, every node keeps k <IP address, UDP port, node ID> triples (as a list) for nodes of distance between 2^i and 2^i+1 from itself. it is called k-buckets. each k-bucket is kept sorted by time last seen–least recently seen node at the head, most-recently seen at the tail. for small values of i, the k-buckets will generally be empty (as no approriate nodes will exist).
\n
The K value mentioned here is a system-level constant (must be an even number). It is set by the software system using Kad (for example, the Kad network used by BT download, K is set to 8).
\n
update of k bucket
There are mainly the following ways to update the K bucket:
\n
\n
Actively collect nodes: Any node can initiate a FIND_NODE (query node) request to refresh the node information in the K-bucket.
\n
Passive collection node: When receiving requests from other nodes (such as: FIND_NODE, FIND_VALUE), it will add the node ID of the other party to a certain K-bucket.
\n
Detect invalid nodes: By initiating a PING request, determine whether a node in the K-bucket is online, and then clean up which offline nodes in the K-bucket.
\n
\n
The update principle is to insert the latest node into the tail of the queue, and not to remove the online nodes in the queue.
\n
According to the K-bucket update principle, nodes with a long online time are more likely to remain in the K-bucket list. Therefore, by keeping the nodes with a long online time in the K-bucket, Kad will significantly increase the number of nodes in the K-bucket. it can defend against DOS attacks to a certain extent, because only when the old node fails, Kad will update the K bucket information, which avoids flooding routing information through the addition of new nodes
\n
RPC method
The Kademlia protocol includes four remote RPC operations: PING, STORE, FIND_NODE, FIND_VALUE.
\n
\n
PING probes a node to see if it is online.
\n
STORE instructs a node to store a <key,value> pair for later retrieval.
\n
FIND_NODE takes a 160bit ID as an argument. The receiver of this operation returns the (IP address, UDP port, Node ID) information of K nodes that it knows are closer to the target ID. The information of these nodes can be obtained from a single K-bucket, or from multiple K-buckets. In either case, the receiver will return the information of K nodes to the operation initiator.
\n
The FIND_VALUE operation is similar to the FIND_NODE operation, with one exception. if the RPC receipients has received a STORE RPC for the key, it just returns the stored value.
\n
\n
node lookup
Kad participant must locate the k closest nodes to some given node ID. Kad employs a recursive algorithm for node lookups. It recursively send FIND_NODE requests to \\alpha (out of k) closest nodes it knows of.
\n
find a <key,value> pair
to find a <key,value> pair, a node starts by performing a lookup to find the k nodes with IDs closest to the key. However, value lookups use FIND_VLAUE rather than FIND_NODE RPCs.
\n
node join
to join the network, a node u must have a contact to an already participating node w.
Kademlia, a peer-to-peer distributed hash table(DHT). Some other DHT techniques are Chord. In the Kad network, each node has a unique 160-bit ID (ETH account address is 20 bytes, which is 160 bits) <key,value> pairs are stored in nodes whose ID is ‘close’ to the key for some notion of closeness.
\n
system description
Kad effectively treats nodes as leaves in a binary tree, with each nodes’s position determined by the shortest unique prefix of its ID. Figure 1 shows the position of a node with unique prefix 0011 in an example.
\n
for any given node, the binary tree is divided into a series of successively lower subtrees that don’t contain the node. The highest-level subtree is composed of the other half of the whole tree that does not contain itself; the next level of subtree is composed of the remaining half that does not contain itself; and so on, until the complete tree is split into n subtrees. As shown in the figure, the part contained by the dotted line is the subtree of node 0011.
\n
if there is at least one node knwon in each subtree (in total, at least n nodes), a recursive routing algorithm can be used to reach any node within the binary tree. Figure 2 shows an example of node 0011 locating node 1110 by successively querying the best node it knows of to find contacts in lower and lower subtrees; finaly the lookup converges to the target node.
\n\n
node distance: XOR metric
Node’s id is 160 bit. Keys are also 160 bit. The Kad algorithm uses an XOR operation to calculate the distance between nodes. d(x,y) = x XOR y
\n
node state
for each 0 <= i < 160, every node keeps k <IP address, UDP port, node ID> triples (as a list) for nodes of distance between 2^i and 2^i+1 from itself. it is called k-buckets. each k-bucket is kept sorted by time last seen–least recently seen node at the head, most-recently seen at the tail. for small values of i, the k-buckets will generally be empty (as no approriate nodes will exist).
\n
The K value mentioned here is a system-level constant (must be an even number). It is set by the software system using Kad (for example, the Kad network used by BT download, K is set to 8).
\n
update of k bucket
There are mainly the following ways to update the K bucket:
\n
\n
Actively collect nodes: Any node can initiate a FIND_NODE (query node) request to refresh the node information in the K-bucket.
\n
Passive collection node: When receiving requests from other nodes (such as: FIND_NODE, FIND_VALUE), it will add the node ID of the other party to a certain K-bucket.
\n
Detect invalid nodes: By initiating a PING request, determine whether a node in the K-bucket is online, and then clean up which offline nodes in the K-bucket.
\n
\n
The update principle is to insert the latest node into the tail of the queue, and not to remove the online nodes in the queue.
\n
According to the K-bucket update principle, nodes with a long online time are more likely to remain in the K-bucket list. Therefore, by keeping the nodes with a long online time in the K-bucket, Kad will significantly increase the number of nodes in the K-bucket. it can defend against DOS attacks to a certain extent, because only when the old node fails, Kad will update the K bucket information, which avoids flooding routing information through the addition of new nodes
\n
RPC method
The Kademlia protocol includes four remote RPC operations: PING, STORE, FIND_NODE, FIND_VALUE.
\n
\n
PING probes a node to see if it is online.
\n
STORE instructs a node to store a <key,value> pair for later retrieval.
\n
FIND_NODE takes a 160bit ID as an argument. The receiver of this operation returns the (IP address, UDP port, Node ID) information of K nodes that it knows are closer to the target ID. The information of these nodes can be obtained from a single K-bucket, or from multiple K-buckets. In either case, the receiver will return the information of K nodes to the operation initiator.
\n
The FIND_VALUE operation is similar to the FIND_NODE operation, with one exception. if the RPC receipients has received a STORE RPC for the key, it just returns the stored value.
\n
\n
node lookup
Kad participant must locate the k closest nodes to some given node ID. Kad employs a recursive algorithm for node lookups. It recursively send FIND_NODE requests to \\alpha (out of k) closest nodes it knows of.
\n
find a <key,value> pair
to find a <key,value> pair, a node starts by performing a lookup to find the k nodes with IDs closest to the key. However, value lookups use FIND_VLAUE rather than FIND_NODE RPCs.
\n
node join
to join the network, a node u must have a contact to an already participating node w.
"},{"title":"geth_fine_tune","date":"2023-01-01T08:29:43.000Z","_content":"\n\nIf we're a full node on mainnet without --cache specified, bump default cache allowance\nctx.Set(utils.CacheFlag.Name, strconv.Itoa(4096))","source":"_posts/geth-fine-tune.md","raw":"---\ntitle: geth_fine_tune\ndate: 2023-01-01 16:29:43\ntags:\n---\n\n\nIf we're a full node on mainnet without --cache specified, bump default cache allowance\nctx.Set(utils.CacheFlag.Name, strconv.Itoa(4096))","slug":"geth-fine-tune","published":1,"updated":"2023-04-25T09:48:14.119Z","comments":1,"layout":"post","photos":[],"link":"","_id":"clk1e4wpo00046hsjbfs3g4aw","content":"
If we’re a full node on mainnet without –cache specified, bump default cache allowance ctx.Set(utils.CacheFlag.Name, strconv.Itoa(4096))
\n","site":{"data":{}},"excerpt":"","more":"
If we’re a full node on mainnet without –cache specified, bump default cache allowance ctx.Set(utils.CacheFlag.Name, strconv.Itoa(4096))
\n"},{"title":"how to use hexo","date":"2022-11-27T03:47:56.000Z","_content":"Welcome to [Hexo](https://hexo.io/)! This is your very first post. Check [documentation](https://hexo.io/docs/) for more info. If you get any problems when using Hexo, you can find the answer in [troubleshooting](https://hexo.io/docs/troubleshooting.html) or you can ask me on [GitHub](https://github.com/hexojs/hexo/issues).\n\n## Quick Start\n\n### Create a new post\n\n``` bash\n$ hexo new \"My New Post\"\n```\n\nMore info: [Writing](https://hexo.io/docs/writing.html)\n\n### Run server\n\n``` bash\n$ hexo server\n```\n\nMore info: [Server](https://hexo.io/docs/server.html)\n\n### Generate static files\n\n``` bash\n$ hexo generate\n```\n\nMore info: [Generating](https://hexo.io/docs/generating.html)\n\n### Deploy to remote sites\n\n``` bash\n$ hexo deploy\n```\n\nMore info: [Deployment](https://hexo.io/docs/one-command-deployment.html)\n","source":"_posts/hello-world.md","raw":"---\ntitle: how to use hexo\ndate: 2022-11-27 11:47:56\n---\nWelcome to [Hexo](https://hexo.io/)! This is your very first post. Check [documentation](https://hexo.io/docs/) for more info. If you get any problems when using Hexo, you can find the answer in [troubleshooting](https://hexo.io/docs/troubleshooting.html) or you can ask me on [GitHub](https://github.com/hexojs/hexo/issues).\n\n## Quick Start\n\n### Create a new post\n\n``` bash\n$ hexo new \"My New Post\"\n```\n\nMore info: [Writing](https://hexo.io/docs/writing.html)\n\n### Run server\n\n``` bash\n$ hexo server\n```\n\nMore info: [Server](https://hexo.io/docs/server.html)\n\n### Generate static files\n\n``` bash\n$ hexo generate\n```\n\nMore info: [Generating](https://hexo.io/docs/generating.html)\n\n### Deploy to remote sites\n\n``` bash\n$ hexo deploy\n```\n\nMore info: [Deployment](https://hexo.io/docs/one-command-deployment.html)\n","slug":"hello-world","published":1,"updated":"2023-04-06T16:43:39.107Z","comments":1,"layout":"post","photos":[],"link":"","_id":"clk1e4wpo00056hsj0dsfahih","content":"
Welcome to Hexo! This is your very first post. Check documentation for more info. If you get any problems when using Hexo, you can find the answer in troubleshooting or you can ask me on GitHub.
Welcome to Hexo! This is your very first post. Check documentation for more info. If you get any problems when using Hexo, you can find the answer in troubleshooting or you can ask me on GitHub.
\n"},{"title":"go similar concepts comparison","date":"2023-03-05T02:44:50.000Z","_content":"\n## struct{} & struct{}{}\n`struct` is a keyword in Go. It is used to define struct types, which is a sequence of named elements.\n\nFor example:\n```go\ntype Person struct {\n Name string\n Age int\n}\n```\nThe `struct{}` is a struct type with zero elements. It is often used when no information is to be stored. It has the benefit of being 0-sized, so usually no memory is required to store a value of type `struct{}`.\n\n`struct{}{}` on the other hand is a [composite literal](https://go.dev/ref/spec#Composite_literals), it constructs a value of type `struct{}`. A composite literal constructs values for types such as `structs`, `arrays`, `maps` and `slices`. Its syntax is the type followed by the elements in braces. Since the \"empty\" struct (struct{}) has no fields, the elements list is also empty:\n\n struct{} {}\n| ^ | ^\n type empty element list\nAs an example let's create a \"set\" in Go. Go does not have a builtin set data structure, but it has a builtin map. We can use a map as a set, as a map can only have at most one entry with a given key. And since we want to only store keys (elements) in the map, we may choose the map value type to be struct{}.\n\nA map with string elements:\n```go\nvar set map[string]struct{}\n// Initialize the set\nset = make(map[string]struct{})\n\n// Add some values to the set:\nset[\"red\"] = struct{}{}\nset[\"blue\"] = struct{}{}\n\n// Check if a value is in the map:\n_, ok := set[\"red\"]\nfmt.Println(\"Is red in the map?\", ok)\n_, ok = set[\"green\"]\nfmt.Println(\"Is green in the map?\", ok)\n```","source":"_posts/golang/go-similar-concepts-comparison.md","raw":"---\ntitle: go similar concepts comparison\ndate: 2023-03-05 10:44:50\ntags: [golang]\n---\n\n## struct{} & struct{}{}\n`struct` is a keyword in Go. It is used to define struct types, which is a sequence of named elements.\n\nFor example:\n```go\ntype Person struct {\n Name string\n Age int\n}\n```\nThe `struct{}` is a struct type with zero elements. It is often used when no information is to be stored. It has the benefit of being 0-sized, so usually no memory is required to store a value of type `struct{}`.\n\n`struct{}{}` on the other hand is a [composite literal](https://go.dev/ref/spec#Composite_literals), it constructs a value of type `struct{}`. A composite literal constructs values for types such as `structs`, `arrays`, `maps` and `slices`. Its syntax is the type followed by the elements in braces. Since the \"empty\" struct (struct{}) has no fields, the elements list is also empty:\n\n struct{} {}\n| ^ | ^\n type empty element list\nAs an example let's create a \"set\" in Go. Go does not have a builtin set data structure, but it has a builtin map. We can use a map as a set, as a map can only have at most one entry with a given key. And since we want to only store keys (elements) in the map, we may choose the map value type to be struct{}.\n\nA map with string elements:\n```go\nvar set map[string]struct{}\n// Initialize the set\nset = make(map[string]struct{})\n\n// Add some values to the set:\nset[\"red\"] = struct{}{}\nset[\"blue\"] = struct{}{}\n\n// Check if a value is in the map:\n_, ok := set[\"red\"]\nfmt.Println(\"Is red in the map?\", ok)\n_, ok = set[\"green\"]\nfmt.Println(\"Is green in the map?\", ok)\n```","slug":"golang/go-similar-concepts-comparison","published":1,"updated":"2023-06-18T07:07:22.116Z","comments":1,"layout":"post","photos":[],"link":"","_id":"clk1e4wpp00076hsjh7rifext","content":"
struct{} & struct{}{}
struct is a keyword in Go. It is used to define struct types, which is a sequence of named elements.
\n
For example:
\n
1 2 3 4
type Person struct { Name string Age int }
\n
The struct{} is a struct type with zero elements. It is often used when no information is to be stored. It has the benefit of being 0-sized, so usually no memory is required to store a value of type struct{}.
\n
struct{}{} on the other hand is a composite literal, it constructs a value of type struct{}. A composite literal constructs values for types such as structs, arrays, maps and slices. Its syntax is the type followed by the elements in braces. Since the “empty” struct (struct{}) has no fields, the elements list is also empty:
\n
struct{} {} | ^ | ^ type empty element list As an example let’s create a “set” in Go. Go does not have a builtin set data structure, but it has a builtin map. We can use a map as a set, as a map can only have at most one entry with a given key. And since we want to only store keys (elements) in the map, we may choose the map value type to be struct{}.
\n
A map with string elements:
\n
1 2 3 4 5 6 7 8 9 10 11 12 13
var set map[string]struct{} // Initialize the set set = make(map[string]struct{})
// Add some values to the set: set["red"] = struct{}{} set["blue"] = struct{}{}
// Check if a value is in the map: _, ok := set["red"] fmt.Println("Is red in the map?", ok) _, ok = set["green"] fmt.Println("Is green in the map?", ok)
","site":{"data":{}},"excerpt":"","more":"
struct{} & struct{}{}
struct is a keyword in Go. It is used to define struct types, which is a sequence of named elements.
\n
For example:
\n
1 2 3 4
type Person struct { Name string Age int }
\n
The struct{} is a struct type with zero elements. It is often used when no information is to be stored. It has the benefit of being 0-sized, so usually no memory is required to store a value of type struct{}.
\n
struct{}{} on the other hand is a composite literal, it constructs a value of type struct{}. A composite literal constructs values for types such as structs, arrays, maps and slices. Its syntax is the type followed by the elements in braces. Since the “empty” struct (struct{}) has no fields, the elements list is also empty:
\n
struct{} {} | ^ | ^ type empty element list As an example let’s create a “set” in Go. Go does not have a builtin set data structure, but it has a builtin map. We can use a map as a set, as a map can only have at most one entry with a given key. And since we want to only store keys (elements) in the map, we may choose the map value type to be struct{}.
\n
A map with string elements:
\n
1 2 3 4 5 6 7 8 9 10 11 12 13
var set map[string]struct{} // Initialize the set set = make(map[string]struct{})
// Add some values to the set: set["red"] = struct{}{} set["blue"] = struct{}{}
// Check if a value is in the map: _, ok := set["red"] fmt.Println("Is red in the map?", ok) _, ok = set["green"] fmt.Println("Is green in the map?", ok)
"},{"title":"go reflect","date":"2023-03-02T02:44:50.000Z","_content":"\n## introduction\nReflection is the ability of a program to examine its own structure, particularly through types. \n\n## type and interfaces\nGo is statically typed. Every variable has a static type, Exactly one type known and fixed at compile time. If we declare\n```go\ntype MyInt int\n\nvar i int\nvar j MyInt\n```\n**The variables i and j have distinct static types and, although they have the same underlying type, they cannot be assigned to one another without a conversion.**\n\nOne important category of type is interface types, which represent fixed sets of methods. An interface variable can store any concrete (non-interface) value as long as that value implements the interface’s methods. An extremely important example of an interface type is the empty interface:\n```go\ninterface{}\n```\nor its equivalent alias,\n```go\nany\n```\nIt represents the empty set of methods and is satisfied by any value at all, since every value has zero or more methods.\na variable of interface type always has the same static type, and even though at run time the value stored in the interface variable may change type, that value will always satisfy the interface.\n\n## the representation of an interface\nA variable of interface type stores a pair: the concrete value assigned to the variable, and that value’s type descriptor.\nFor instance, after\n```golang\nvar r io.Reader\ntty, err := os.OpenFile(\"/dev/tty\", os.O_RDWR, 0)\nif err != nil {\n return nil, err\n}\nr = tty\n```\nr contains, schematically, the (value, type) pair, (tty, *os.File). Notice that the type *os.File implements methods other than Read; even though the interface value provides access only to the Read method, the value inside carries all the type information about that value. That’s why we can do things like this:\n```go\nvar w io.Writer\nw = r.(io.Writer)\n```\nThe expression in this assignment is a type assertion; what it asserts is that the item inside r also implements io.Writer, and so we can assign it to w. After the assignment, w will contain the pair (tty, *os.File). That’s the same pair as was held in r. \nOne important detail is that the pair inside an interface variable always has the form (value, concrete type) and cannot have the form (value, interface type). Interfaces do not hold interface values.\n\n## the first law of reflection\n1. Reflection goes from interface value to reflection object\nAt the basic level, reflection is just a mechanism to examine the type and value pair stored inside an interface variable. `reflect.TypeOf` and `reflect.ValueOf`, retrieve `reflect.Type` and `reflect.Value` pieces out of an interface value.\n```go\nvar x float64 = 3.4\nfmt.Println(\"type:\", reflect.TypeOf(x))\n```\n```\ntype: float64\n```\n```go\nvar x float64 = 3.4\nv := reflect.ValueOf(x)\nfmt.Println(\"type:\", v.Type())\nfmt.Println(\"kind is float64:\", v.Kind() == reflect.Float64)\nfmt.Println(\"value:\", v.Float())\n```\n```\ntype: float64\nkind is float64: true\nvalue: 3.4\n```\nThere are also methods like SetInt and SetFloat. **to keep the API simple, the “getter” and “setter” methods of Value operate on the largest type that can hold the value**: int64 for all the signed integers, for instance. \n```go\nvar x uint8 = 'x'\nv := reflect.ValueOf(x)\nfmt.Println(\"type:\", v.Type()) // uint8.\nfmt.Println(\"kind is uint8: \", v.Kind() == reflect.Uint8) // true.\nx = uint8(v.Uint()) // v.Uint returns a uint64.\n```\n\n2. Reflection goes from reflection object to interface value.\nGiven a reflect.Value we can recover an interface value using the Interface method;\n```go\n// Interface returns v's current value as an interface{}.\n// It is equivalent to:\n//\n//\tvar i interface{} = (v's underlying value)\nfunc (v Value) Interface() interface{}\n```\n```go\ny := v.Interface().(float64) // y will have type float64.\nfmt.Println(y)\n```\n\n3. To modify a reflection object, the value must be settable.\nThe CanSet method of Value reports the settability of a Value; in our case,\n```go\nvar x float64 = 3.4\nv := reflect.ValueOf(x)\nfmt.Println(\"settability of v:\", v.CanSet())\n```\n```\nsettability of v: false\n```\nwe pass a copy of x to reflect.ValueOf, so the interface value created as the argument to reflect.ValueOf is a copy of x, not x itself. Thus, if the statement `v.SetFloat(7.1)` were allowed to succeed, it would not update x, even though v looks like it was created from x. Instead, it would update the copy of x stored inside the reflection value and x itself would be unaffected. That would be confusing and useless, so it is illegal, and settability is the property used to avoid this issue. If we want to modify x by reflection, we must give the reflection library a pointer to the value we want to modify.\nLet’s do that. \n```go\nvar x float64 = 3.4\np := reflect.ValueOf(&x) // Note: take the address of x.\nfmt.Println(\"type of p:\", p.Type())\nfmt.Println(\"settability of p:\", p.CanSet())\n```\nThe reflection object p isn’t settable, but it’s not p we want to set, it’s (in effect) *p. To get to what p points to, we call the Elem method of Value, which indirects through the pointer, and save the result in a reflection Value called v:\n```go\nv := p.Elem()\nfmt.Println(\"settability of v:\", v.CanSet())\n```\n```\nsettability of v: true\n```\n\n## structs\n\n```go\ntype T struct {\n A int\n B string\n}\nt := T{23, \"skidoo\"}\ns := reflect.ValueOf(&t).Elem()\ntypeOfT := s.Type()\nfor i := 0; i < s.NumField(); i++ {\n f := s.Field(i)\n fmt.Printf(\"%d: %s %s = %v\\n\", i,\n typeOfT.Field(i).Name, f.Type(), f.Interface())\n}\n```\n```\n0: A int = 23\n1: B string = skidoo\n```\nThere’s one more point about settability introduced in passing here: the field names of T are upper case (exported) because only exported fields of a struct are settable.\nBecause s contains a settable reflection object, we can modify the fields of the structure.\n```\ns.Field(0).SetInt(77)\ns.Field(1).SetString(\"Sunset Strip\")\nfmt.Println(\"t is now\", t)\n```\nIf we modified the program so that s was created from t, not &t, the calls to SetInt and SetString would fail as the fields of t would not be settable.\n\n## references\n- [official blog](https://go.dev/blog/laws-of-reflection)\n- [go data structure: interface](https://research.swtch.com/interfaces)","source":"_posts/golang/go-reflect.md","raw":"---\ntitle: go reflect\ndate: 2023-03-02 10:44:50\ntags: [golang]\n---\n\n## introduction\nReflection is the ability of a program to examine its own structure, particularly through types. \n\n## type and interfaces\nGo is statically typed. Every variable has a static type, Exactly one type known and fixed at compile time. If we declare\n```go\ntype MyInt int\n\nvar i int\nvar j MyInt\n```\n**The variables i and j have distinct static types and, although they have the same underlying type, they cannot be assigned to one another without a conversion.**\n\nOne important category of type is interface types, which represent fixed sets of methods. An interface variable can store any concrete (non-interface) value as long as that value implements the interface’s methods. An extremely important example of an interface type is the empty interface:\n```go\ninterface{}\n```\nor its equivalent alias,\n```go\nany\n```\nIt represents the empty set of methods and is satisfied by any value at all, since every value has zero or more methods.\na variable of interface type always has the same static type, and even though at run time the value stored in the interface variable may change type, that value will always satisfy the interface.\n\n## the representation of an interface\nA variable of interface type stores a pair: the concrete value assigned to the variable, and that value’s type descriptor.\nFor instance, after\n```golang\nvar r io.Reader\ntty, err := os.OpenFile(\"/dev/tty\", os.O_RDWR, 0)\nif err != nil {\n return nil, err\n}\nr = tty\n```\nr contains, schematically, the (value, type) pair, (tty, *os.File). Notice that the type *os.File implements methods other than Read; even though the interface value provides access only to the Read method, the value inside carries all the type information about that value. That’s why we can do things like this:\n```go\nvar w io.Writer\nw = r.(io.Writer)\n```\nThe expression in this assignment is a type assertion; what it asserts is that the item inside r also implements io.Writer, and so we can assign it to w. After the assignment, w will contain the pair (tty, *os.File). That’s the same pair as was held in r. \nOne important detail is that the pair inside an interface variable always has the form (value, concrete type) and cannot have the form (value, interface type). Interfaces do not hold interface values.\n\n## the first law of reflection\n1. Reflection goes from interface value to reflection object\nAt the basic level, reflection is just a mechanism to examine the type and value pair stored inside an interface variable. `reflect.TypeOf` and `reflect.ValueOf`, retrieve `reflect.Type` and `reflect.Value` pieces out of an interface value.\n```go\nvar x float64 = 3.4\nfmt.Println(\"type:\", reflect.TypeOf(x))\n```\n```\ntype: float64\n```\n```go\nvar x float64 = 3.4\nv := reflect.ValueOf(x)\nfmt.Println(\"type:\", v.Type())\nfmt.Println(\"kind is float64:\", v.Kind() == reflect.Float64)\nfmt.Println(\"value:\", v.Float())\n```\n```\ntype: float64\nkind is float64: true\nvalue: 3.4\n```\nThere are also methods like SetInt and SetFloat. **to keep the API simple, the “getter” and “setter” methods of Value operate on the largest type that can hold the value**: int64 for all the signed integers, for instance. \n```go\nvar x uint8 = 'x'\nv := reflect.ValueOf(x)\nfmt.Println(\"type:\", v.Type()) // uint8.\nfmt.Println(\"kind is uint8: \", v.Kind() == reflect.Uint8) // true.\nx = uint8(v.Uint()) // v.Uint returns a uint64.\n```\n\n2. Reflection goes from reflection object to interface value.\nGiven a reflect.Value we can recover an interface value using the Interface method;\n```go\n// Interface returns v's current value as an interface{}.\n// It is equivalent to:\n//\n//\tvar i interface{} = (v's underlying value)\nfunc (v Value) Interface() interface{}\n```\n```go\ny := v.Interface().(float64) // y will have type float64.\nfmt.Println(y)\n```\n\n3. To modify a reflection object, the value must be settable.\nThe CanSet method of Value reports the settability of a Value; in our case,\n```go\nvar x float64 = 3.4\nv := reflect.ValueOf(x)\nfmt.Println(\"settability of v:\", v.CanSet())\n```\n```\nsettability of v: false\n```\nwe pass a copy of x to reflect.ValueOf, so the interface value created as the argument to reflect.ValueOf is a copy of x, not x itself. Thus, if the statement `v.SetFloat(7.1)` were allowed to succeed, it would not update x, even though v looks like it was created from x. Instead, it would update the copy of x stored inside the reflection value and x itself would be unaffected. That would be confusing and useless, so it is illegal, and settability is the property used to avoid this issue. If we want to modify x by reflection, we must give the reflection library a pointer to the value we want to modify.\nLet’s do that. \n```go\nvar x float64 = 3.4\np := reflect.ValueOf(&x) // Note: take the address of x.\nfmt.Println(\"type of p:\", p.Type())\nfmt.Println(\"settability of p:\", p.CanSet())\n```\nThe reflection object p isn’t settable, but it’s not p we want to set, it’s (in effect) *p. To get to what p points to, we call the Elem method of Value, which indirects through the pointer, and save the result in a reflection Value called v:\n```go\nv := p.Elem()\nfmt.Println(\"settability of v:\", v.CanSet())\n```\n```\nsettability of v: true\n```\n\n## structs\n\n```go\ntype T struct {\n A int\n B string\n}\nt := T{23, \"skidoo\"}\ns := reflect.ValueOf(&t).Elem()\ntypeOfT := s.Type()\nfor i := 0; i < s.NumField(); i++ {\n f := s.Field(i)\n fmt.Printf(\"%d: %s %s = %v\\n\", i,\n typeOfT.Field(i).Name, f.Type(), f.Interface())\n}\n```\n```\n0: A int = 23\n1: B string = skidoo\n```\nThere’s one more point about settability introduced in passing here: the field names of T are upper case (exported) because only exported fields of a struct are settable.\nBecause s contains a settable reflection object, we can modify the fields of the structure.\n```\ns.Field(0).SetInt(77)\ns.Field(1).SetString(\"Sunset Strip\")\nfmt.Println(\"t is now\", t)\n```\nIf we modified the program so that s was created from t, not &t, the calls to SetInt and SetString would fail as the fields of t would not be settable.\n\n## references\n- [official blog](https://go.dev/blog/laws-of-reflection)\n- [go data structure: interface](https://research.swtch.com/interfaces)","slug":"golang/go-reflect","published":1,"updated":"2023-06-18T06:42:44.968Z","comments":1,"layout":"post","photos":[],"link":"","_id":"clk1e4wpp00086hsjfqu01qqy","content":"
introduction
Reflection is the ability of a program to examine its own structure, particularly through types.
\n
type and interfaces
Go is statically typed. Every variable has a static type, Exactly one type known and fixed at compile time. If we declare
\n
1 2 3 4
type MyInt int
var i int var j MyInt
\n
The variables i and j have distinct static types and, although they have the same underlying type, they cannot be assigned to one another without a conversion.
\n
One important category of type is interface types, which represent fixed sets of methods. An interface variable can store any concrete (non-interface) value as long as that value implements the interface’s methods. An extremely important example of an interface type is the empty interface:
\n
1
interface{}
\n
or its equivalent alias,
\n
1
any
\n
It represents the empty set of methods and is satisfied by any value at all, since every value has zero or more methods. a variable of interface type always has the same static type, and even though at run time the value stored in the interface variable may change type, that value will always satisfy the interface.
\n
the representation of an interface
A variable of interface type stores a pair: the concrete value assigned to the variable, and that value’s type descriptor. For instance, after
\n
1 2 3 4 5 6
var r io.Reader tty, err := os.OpenFile("/dev/tty", os.O_RDWR, 0) if err != nil { returnnil, err } r = tty
\n
r contains, schematically, the (value, type) pair, (tty, *os.File). Notice that the type *os.File implements methods other than Read; even though the interface value provides access only to the Read method, the value inside carries all the type information about that value. That’s why we can do things like this:
\n
1 2
var w io.Writer w = r.(io.Writer)
\n
The expression in this assignment is a type assertion; what it asserts is that the item inside r also implements io.Writer, and so we can assign it to w. After the assignment, w will contain the pair (tty, *os.File). That’s the same pair as was held in r. One important detail is that the pair inside an interface variable always has the form (value, concrete type) and cannot have the form (value, interface type). Interfaces do not hold interface values.
\n
the first law of reflection
\n
Reflection goes from interface value to reflection object At the basic level, reflection is just a mechanism to examine the type and value pair stored inside an interface variable. reflect.TypeOf and reflect.ValueOf, retrieve reflect.Type and reflect.Value pieces out of an interface value.
\n
1 2
var x float64 = 3.4 fmt.Println("type:", reflect.TypeOf(x))
\n
1
type: float64
\n
1 2 3 4 5
var x float64 = 3.4 v := reflect.ValueOf(x) fmt.Println("type:", v.Type()) fmt.Println("kind is float64:", v.Kind() == reflect.Float64) fmt.Println("value:", v.Float())
\n
1 2 3
type: float64 kind is float64: true value: 3.4
\n
There are also methods like SetInt and SetFloat. to keep the API simple, the “getter” and “setter” methods of Value operate on the largest type that can hold the value: int64 for all the signed integers, for instance.
\n
1 2 3 4 5
var x uint8 = 'x' v := reflect.ValueOf(x) fmt.Println("type:", v.Type()) // uint8. fmt.Println("kind is uint8: ", v.Kind() == reflect.Uint8) // true. x = uint8(v.Uint()) // v.Uint returns a uint64.
\n
\n
Reflection goes from reflection object to interface value. Given a reflect.Value we can recover an interface value using the Interface method;
\n
1 2 3 4 5
// Interface returns v's current value as an interface{}. // It is equivalent to: // //\tvar i interface{} = (v's underlying value) func(v Value) Interface() interface{}
\n
1 2
y := v.Interface().(float64) // y will have type float64. fmt.Println(y)
\n
\n
To modify a reflection object, the value must be settable. The CanSet method of Value reports the settability of a Value; in our case,
\n
1 2 3
var x float64 = 3.4 v := reflect.ValueOf(x) fmt.Println("settability of v:", v.CanSet())
\n
1
settability of v: false
\n
we pass a copy of x to reflect.ValueOf, so the interface value created as the argument to reflect.ValueOf is a copy of x, not x itself. Thus, if the statement v.SetFloat(7.1) were allowed to succeed, it would not update x, even though v looks like it was created from x. Instead, it would update the copy of x stored inside the reflection value and x itself would be unaffected. That would be confusing and useless, so it is illegal, and settability is the property used to avoid this issue. If we want to modify x by reflection, we must give the reflection library a pointer to the value we want to modify. Let’s do that.
\n
1 2 3 4
var x float64 = 3.4 p := reflect.ValueOf(&x) // Note: take the address of x. fmt.Println("type of p:", p.Type()) fmt.Println("settability of p:", p.CanSet())
\n
The reflection object p isn’t settable, but it’s not p we want to set, it’s (in effect) *p. To get to what p points to, we call the Elem method of Value, which indirects through the pointer, and save the result in a reflection Value called v:
\n
1 2
v := p.Elem() fmt.Println("settability of v:", v.CanSet())
\n
1
settability of v: true
\n\n
structs
1 2 3 4 5 6 7 8 9 10 11 12
type T struct { A int B string } t := T{23, "skidoo"} s := reflect.ValueOf(&t).Elem() typeOfT := s.Type() for i := 0; i < s.NumField(); i++ { f := s.Field(i) fmt.Printf("%d: %s %s = %v\\n", i, typeOfT.Field(i).Name, f.Type(), f.Interface()) }
\n
1 2
0: A int = 23 1: B string = skidoo
\n
There’s one more point about settability introduced in passing here: the field names of T are upper case (exported) because only exported fields of a struct are settable. Because s contains a settable reflection object, we can modify the fields of the structure.
\n
1 2 3
s.Field(0).SetInt(77) s.Field(1).SetString("Sunset Strip") fmt.Println("t is now", t)
\n
If we modified the program so that s was created from t, not &t, the calls to SetInt and SetString would fail as the fields of t would not be settable.
Reflection is the ability of a program to examine its own structure, particularly through types.
\n
type and interfaces
Go is statically typed. Every variable has a static type, Exactly one type known and fixed at compile time. If we declare
\n
1 2 3 4
type MyInt int
var i int var j MyInt
\n
The variables i and j have distinct static types and, although they have the same underlying type, they cannot be assigned to one another without a conversion.
\n
One important category of type is interface types, which represent fixed sets of methods. An interface variable can store any concrete (non-interface) value as long as that value implements the interface’s methods. An extremely important example of an interface type is the empty interface:
\n
1
interface{}
\n
or its equivalent alias,
\n
1
any
\n
It represents the empty set of methods and is satisfied by any value at all, since every value has zero or more methods. a variable of interface type always has the same static type, and even though at run time the value stored in the interface variable may change type, that value will always satisfy the interface.
\n
the representation of an interface
A variable of interface type stores a pair: the concrete value assigned to the variable, and that value’s type descriptor. For instance, after
\n
1 2 3 4 5 6
var r io.Reader tty, err := os.OpenFile("/dev/tty", os.O_RDWR, 0) if err != nil { returnnil, err } r = tty
\n
r contains, schematically, the (value, type) pair, (tty, *os.File). Notice that the type *os.File implements methods other than Read; even though the interface value provides access only to the Read method, the value inside carries all the type information about that value. That’s why we can do things like this:
\n
1 2
var w io.Writer w = r.(io.Writer)
\n
The expression in this assignment is a type assertion; what it asserts is that the item inside r also implements io.Writer, and so we can assign it to w. After the assignment, w will contain the pair (tty, *os.File). That’s the same pair as was held in r. One important detail is that the pair inside an interface variable always has the form (value, concrete type) and cannot have the form (value, interface type). Interfaces do not hold interface values.
\n
the first law of reflection
\n
Reflection goes from interface value to reflection object At the basic level, reflection is just a mechanism to examine the type and value pair stored inside an interface variable. reflect.TypeOf and reflect.ValueOf, retrieve reflect.Type and reflect.Value pieces out of an interface value.
\n
1 2
var x float64 = 3.4 fmt.Println("type:", reflect.TypeOf(x))
\n
1
type: float64
\n
1 2 3 4 5
var x float64 = 3.4 v := reflect.ValueOf(x) fmt.Println("type:", v.Type()) fmt.Println("kind is float64:", v.Kind() == reflect.Float64) fmt.Println("value:", v.Float())
\n
1 2 3
type: float64 kind is float64: true value: 3.4
\n
There are also methods like SetInt and SetFloat. to keep the API simple, the “getter” and “setter” methods of Value operate on the largest type that can hold the value: int64 for all the signed integers, for instance.
\n
1 2 3 4 5
var x uint8 = 'x' v := reflect.ValueOf(x) fmt.Println("type:", v.Type()) // uint8. fmt.Println("kind is uint8: ", v.Kind() == reflect.Uint8) // true. x = uint8(v.Uint()) // v.Uint returns a uint64.
\n
\n
Reflection goes from reflection object to interface value. Given a reflect.Value we can recover an interface value using the Interface method;
\n
1 2 3 4 5
// Interface returns v's current value as an interface{}. // It is equivalent to: // //\tvar i interface{} = (v's underlying value) func(v Value) Interface() interface{}
\n
1 2
y := v.Interface().(float64) // y will have type float64. fmt.Println(y)
\n
\n
To modify a reflection object, the value must be settable. The CanSet method of Value reports the settability of a Value; in our case,
\n
1 2 3
var x float64 = 3.4 v := reflect.ValueOf(x) fmt.Println("settability of v:", v.CanSet())
\n
1
settability of v: false
\n
we pass a copy of x to reflect.ValueOf, so the interface value created as the argument to reflect.ValueOf is a copy of x, not x itself. Thus, if the statement v.SetFloat(7.1) were allowed to succeed, it would not update x, even though v looks like it was created from x. Instead, it would update the copy of x stored inside the reflection value and x itself would be unaffected. That would be confusing and useless, so it is illegal, and settability is the property used to avoid this issue. If we want to modify x by reflection, we must give the reflection library a pointer to the value we want to modify. Let’s do that.
\n
1 2 3 4
var x float64 = 3.4 p := reflect.ValueOf(&x) // Note: take the address of x. fmt.Println("type of p:", p.Type()) fmt.Println("settability of p:", p.CanSet())
\n
The reflection object p isn’t settable, but it’s not p we want to set, it’s (in effect) *p. To get to what p points to, we call the Elem method of Value, which indirects through the pointer, and save the result in a reflection Value called v:
\n
1 2
v := p.Elem() fmt.Println("settability of v:", v.CanSet())
\n
1
settability of v: true
\n\n
structs
1 2 3 4 5 6 7 8 9 10 11 12
type T struct { A int B string } t := T{23, "skidoo"} s := reflect.ValueOf(&t).Elem() typeOfT := s.Type() for i := 0; i < s.NumField(); i++ { f := s.Field(i) fmt.Printf("%d: %s %s = %v\\n", i, typeOfT.Field(i).Name, f.Type(), f.Interface()) }
\n
1 2
0: A int = 23 1: B string = skidoo
\n
There’s one more point about settability introduced in passing here: the field names of T are upper case (exported) because only exported fields of a struct are settable. Because s contains a settable reflection object, we can modify the fields of the structure.
\n
1 2 3
s.Field(0).SetInt(77) s.Field(1).SetString("Sunset Strip") fmt.Println("t is now", t)
\n
If we modified the program so that s was created from t, not &t, the calls to SetInt and SetString would fail as the fields of t would not be settable.
\n"},{"title":"rust ownership","date":"2022-10-11T09:09:28.000Z","_content":"\n## ownership rule\n- Each value in Rust has an owner.\n- There can only be one owner at a time.\n- When the owner goes out of scope, the value will be dropped.\n\n## variable scope\n```rust\nfn main() {\n { // s is not valid here, it’s not yet declared\n let s = \"hello\"; // s is valid from this point forward\n // do stuff with s\n } // this scope is now over, and s is no longer valid\n}\n```\n\n## Move\n### stack-only data: Copy trait\nsuch as primitive type\n```rust\nfn main() {\n let x = 5;\n let y = x;\n}\n```\nbind the value 5 to x; then make a copy of the value in x and bind it to y.\n\n### for heap variable\n```rust\nfn main() {\n let s1 = String::from(\"hello\");\n let s2 = s1;\n}\n```\n![move-string](/images/rust/ownership/move-string.png)\nptr, len, capacity is stored in stack, while string value is stored in heap \\\nWhen we assign s1 to s2, the String data is copied, meaning we copy the pointer, the length, and the capacity that are on the stack. We do not copy the data on the heap\n![move-string-2](/images/rust/ownership/move-string-2.png)\nsimilar to shallow copy\n\n## Clone\n```rust\nfn main() {\n let s1 = String::from(\"hello\");\n let s2 = s1.clone();\n\n println!(\"s1 = {}, s2 = {}\", s1, s2);\n}\n```\nIf we do want to deeply copy the heap data of the String, not just the stack data, we can use a common method called clone.\n\n### ownership and function\n- Passing a value to a function will result in a move or copy of ownership\n- difference between \"stack\" and \"heap\" variables: stack variables will be copied, and heap variables will be moved. When a variable containing heap data leaves the scope, its value will be cleared by the drop function, unless the ownership of the data is moved to another variable\n```rust\nfn main() {\n let s = String::from(\"hello\"); // s comes into scope\n takes_ownership(s); // s's value moves into the function...\n // ... and so is no longer valid here\n\n let x = 5; // x comes into scope\n\n makes_copy(x); // x would move into the function,\n // but i32 is Copy, so it's okay to still\n // use x afterward\n\n} // Here, x goes out of scope, then s. But because s's value was moved, nothing\n // special happens.\n\nfn takes_ownership(some_string: String) { // some_string comes into scope\n println!(\"{}\", some_string);\n} // Here, some_string goes out of scope and `drop` is called. The backing\n // memory is freed.\n\nfn makes_copy(some_integer: i32) { // some_integer comes into scope\n println!(\"{}\", some_integer);\n} // Here, some_integer goes out of scope. Nothing special happens.\n\n```\n\n### return values and scope\n```rust\nfn main() {\n let s1 = gives_ownership(); // gives_ownership moves its return\n // value into s1\n\n let s2 = String::from(\"hello\"); // s2 comes into scope\n\n let s3 = takes_and_gives_back(s2); // s2 is moved into\n // takes_and_gives_back, which also\n // moves its return value into s3\n} // Here, s3 goes out of scope and is dropped. s2 was moved, so nothing\n // happens. s1 goes out of scope and is dropped.\n\nfn gives_ownership() -> String { // gives_ownership will move its\n // return value into the function\n // that calls it\n\n let some_string = String::from(\"yours\"); // some_string comes into scope\n\n some_string // some_string is returned and\n // moves out to the calling\n // function\n}\n\n// This function takes a String and returns one\nfn takes_and_gives_back(a_string: String) -> String { // a_string comes into\n // scope\n\n a_string // a_string is returned and moves out to the calling function\n}\n```\n> What if we want to let a function use a value but not take ownership? \n> that's reference\n \n\n## reference & borrow\n- & means reference (borrow but not own), default immutable\n- &mut a mutable reference, only one mutable reference allowed in same scope (avoid data racing)\n- Multiple mutable references can be created non-simultaneously by creating a new scope\n- **Cannot have mutable and immutable references at the same time**\n```rust\nfn main() {\n let mut s = String::from(\"hello\");\n {\n let s1 = &mut s;\n } // r1 goes out of scope here, so we can make a new reference with no problems.\n let s2 = &mut s;\n}\n\nfn main() {\n let mut s = String::from(\"hello\");\n\n let r1 = &s; // no problem\n let r2 = &s; // no problem\n println!(\"{} and {}\", r1, r2);\n // variables r1 and r2 will not be used after this point\n\n let r3 = &mut s; // no problem\n println!(\"{}\", r3);\n\n println!{\"{}\",r1} // got problem with above mutable borrow\n}\n```\n\n### reference as function arguments\n```rust\nfn main() {\n let s1 = String::from(\"hello\");\n\n let len = calculate_length(&s1);\n\n println!(\"The length of '{}' is {}.\", s1, len);\n}\n\nfn calculate_length(s: &String) -> usize { // s is a reference to a String\n s.len() \n} // Here, s goes out of scope. But because it does not have ownership of what\n // it refers to, nothing happens.\n```\nwe pass &s1 into calculate_length and, in its definition, we take &String rather than String. These ampersands represent references, and they allow you to refer to some value without taking ownership of it. Because it does not own it, the value it points to will not be dropped when the reference stops being used. \\\n When functions have references as parameters instead of the actual values, we won't need to return the values in order to give back ownership, because we never had ownership. \\\n We call the action of creating a reference borrowing. \n\n### mutable references\n```rust\nfn main() {\n let mut s = String::from(\"hello\");\n\n change(&mut s);\n}\n\nfn change(some_string: &mut String) {\n some_string.push_str(\", world\");\n}\n```\n\n### dangling references\n- A pointer refers to an address in memory, but the memory may have been freed and allocated for use by someone else\n- rust,The compiler can guarantee that there will never be dangling references\n```rust\nfn main() {\n let r = dangle();\n}\nfn dangle() -> &string { // dangle returns a reference to a String\n let s = String::from(\"hello\"); // s is a new String\n &s // we return a reference to the String, s\n} // Here, s goes out of scope, and is dropped. Its memory goes away.\n// Danger\n```\nThe solution here is to return the String directly:\n```rust\nfn main() {\n let string = no_dangle();\n}\n\nfn no_dangle() -> String {\n let s = String::from(\"hello\");\n s\n}\n```\nThis works without any problems. Ownership is moved out, and nothing is deallocated.\n\n\n## slice\n- Slices let you reference a contiguous sequence of elements in a collection rather than the whole collection. A slice is a kind of reference, so it does not have ownership.\n\n### string slice\n```rust\nfn main() {\n let mut s = String::from(\"Hello world\");\n\n let hello = &s[0..5]; \n let world = &s[6..11];\n}\n```\nRather than a reference to the entire String, hello is a reference to a portion of the String, \\\nWith Rust's `..` range syntax, if you want to start at index zero, you can drop the value before the two periods \\\nBy the same token, if your slice includes the last byte of the String, you can drop the trailing number. \n> Note: String slice range indices must occur at **valid UTF-8 character boundaries**. If you attempt to create a string slice in the middle of a multibyte character, your program will exit with an error.\n\n```rust\nfn first_word(s :&String) -> &str {\n let bytes = s.as_bytes();\n for(i, &item) in bytes.iter().enumerate() {\n if item == b' ' {\n return &s[..i];\n }\n }\n &s[..]\n}\n```\n\n### String Literals Are Slices\n```rust\nfn main() {\nlet s = \"Hello, world!\";\n}\n```\nThe type of s here is &str: it's a slice pointing to that specific point of the binary. \n\n### String Slices as Parameters\n- Pass &str as a parameter, you can receive parameters of type &String and &str at the same time\n```rust\nfn first_word(s: &String) -> &str\n```\nequivalent to\n```rust\nfn first_word(s: &str) -> &str\n```\n\n### other slices\narray slice\n```rust\nfn main() {\n let a = [1, 2, 3, 4, 5];\n let slice = &a[1..3];\n assert_eq!(slice, &[2, 3]);\n}\n```","source":"_posts/rust/rust-03-ownership.md","raw":"---\ntitle: rust ownership\ndate: 2022-10-11 17:09:28\ntags: [rust]\n---\n\n## ownership rule\n- Each value in Rust has an owner.\n- There can only be one owner at a time.\n- When the owner goes out of scope, the value will be dropped.\n\n## variable scope\n```rust\nfn main() {\n { // s is not valid here, it’s not yet declared\n let s = \"hello\"; // s is valid from this point forward\n // do stuff with s\n } // this scope is now over, and s is no longer valid\n}\n```\n\n## Move\n### stack-only data: Copy trait\nsuch as primitive type\n```rust\nfn main() {\n let x = 5;\n let y = x;\n}\n```\nbind the value 5 to x; then make a copy of the value in x and bind it to y.\n\n### for heap variable\n```rust\nfn main() {\n let s1 = String::from(\"hello\");\n let s2 = s1;\n}\n```\n![move-string](/images/rust/ownership/move-string.png)\nptr, len, capacity is stored in stack, while string value is stored in heap \\\nWhen we assign s1 to s2, the String data is copied, meaning we copy the pointer, the length, and the capacity that are on the stack. We do not copy the data on the heap\n![move-string-2](/images/rust/ownership/move-string-2.png)\nsimilar to shallow copy\n\n## Clone\n```rust\nfn main() {\n let s1 = String::from(\"hello\");\n let s2 = s1.clone();\n\n println!(\"s1 = {}, s2 = {}\", s1, s2);\n}\n```\nIf we do want to deeply copy the heap data of the String, not just the stack data, we can use a common method called clone.\n\n### ownership and function\n- Passing a value to a function will result in a move or copy of ownership\n- difference between \"stack\" and \"heap\" variables: stack variables will be copied, and heap variables will be moved. When a variable containing heap data leaves the scope, its value will be cleared by the drop function, unless the ownership of the data is moved to another variable\n```rust\nfn main() {\n let s = String::from(\"hello\"); // s comes into scope\n takes_ownership(s); // s's value moves into the function...\n // ... and so is no longer valid here\n\n let x = 5; // x comes into scope\n\n makes_copy(x); // x would move into the function,\n // but i32 is Copy, so it's okay to still\n // use x afterward\n\n} // Here, x goes out of scope, then s. But because s's value was moved, nothing\n // special happens.\n\nfn takes_ownership(some_string: String) { // some_string comes into scope\n println!(\"{}\", some_string);\n} // Here, some_string goes out of scope and `drop` is called. The backing\n // memory is freed.\n\nfn makes_copy(some_integer: i32) { // some_integer comes into scope\n println!(\"{}\", some_integer);\n} // Here, some_integer goes out of scope. Nothing special happens.\n\n```\n\n### return values and scope\n```rust\nfn main() {\n let s1 = gives_ownership(); // gives_ownership moves its return\n // value into s1\n\n let s2 = String::from(\"hello\"); // s2 comes into scope\n\n let s3 = takes_and_gives_back(s2); // s2 is moved into\n // takes_and_gives_back, which also\n // moves its return value into s3\n} // Here, s3 goes out of scope and is dropped. s2 was moved, so nothing\n // happens. s1 goes out of scope and is dropped.\n\nfn gives_ownership() -> String { // gives_ownership will move its\n // return value into the function\n // that calls it\n\n let some_string = String::from(\"yours\"); // some_string comes into scope\n\n some_string // some_string is returned and\n // moves out to the calling\n // function\n}\n\n// This function takes a String and returns one\nfn takes_and_gives_back(a_string: String) -> String { // a_string comes into\n // scope\n\n a_string // a_string is returned and moves out to the calling function\n}\n```\n> What if we want to let a function use a value but not take ownership? \n> that's reference\n \n\n## reference & borrow\n- & means reference (borrow but not own), default immutable\n- &mut a mutable reference, only one mutable reference allowed in same scope (avoid data racing)\n- Multiple mutable references can be created non-simultaneously by creating a new scope\n- **Cannot have mutable and immutable references at the same time**\n```rust\nfn main() {\n let mut s = String::from(\"hello\");\n {\n let s1 = &mut s;\n } // r1 goes out of scope here, so we can make a new reference with no problems.\n let s2 = &mut s;\n}\n\nfn main() {\n let mut s = String::from(\"hello\");\n\n let r1 = &s; // no problem\n let r2 = &s; // no problem\n println!(\"{} and {}\", r1, r2);\n // variables r1 and r2 will not be used after this point\n\n let r3 = &mut s; // no problem\n println!(\"{}\", r3);\n\n println!{\"{}\",r1} // got problem with above mutable borrow\n}\n```\n\n### reference as function arguments\n```rust\nfn main() {\n let s1 = String::from(\"hello\");\n\n let len = calculate_length(&s1);\n\n println!(\"The length of '{}' is {}.\", s1, len);\n}\n\nfn calculate_length(s: &String) -> usize { // s is a reference to a String\n s.len() \n} // Here, s goes out of scope. But because it does not have ownership of what\n // it refers to, nothing happens.\n```\nwe pass &s1 into calculate_length and, in its definition, we take &String rather than String. These ampersands represent references, and they allow you to refer to some value without taking ownership of it. Because it does not own it, the value it points to will not be dropped when the reference stops being used. \\\n When functions have references as parameters instead of the actual values, we won't need to return the values in order to give back ownership, because we never had ownership. \\\n We call the action of creating a reference borrowing. \n\n### mutable references\n```rust\nfn main() {\n let mut s = String::from(\"hello\");\n\n change(&mut s);\n}\n\nfn change(some_string: &mut String) {\n some_string.push_str(\", world\");\n}\n```\n\n### dangling references\n- A pointer refers to an address in memory, but the memory may have been freed and allocated for use by someone else\n- rust,The compiler can guarantee that there will never be dangling references\n```rust\nfn main() {\n let r = dangle();\n}\nfn dangle() -> &string { // dangle returns a reference to a String\n let s = String::from(\"hello\"); // s is a new String\n &s // we return a reference to the String, s\n} // Here, s goes out of scope, and is dropped. Its memory goes away.\n// Danger\n```\nThe solution here is to return the String directly:\n```rust\nfn main() {\n let string = no_dangle();\n}\n\nfn no_dangle() -> String {\n let s = String::from(\"hello\");\n s\n}\n```\nThis works without any problems. Ownership is moved out, and nothing is deallocated.\n\n\n## slice\n- Slices let you reference a contiguous sequence of elements in a collection rather than the whole collection. A slice is a kind of reference, so it does not have ownership.\n\n### string slice\n```rust\nfn main() {\n let mut s = String::from(\"Hello world\");\n\n let hello = &s[0..5]; \n let world = &s[6..11];\n}\n```\nRather than a reference to the entire String, hello is a reference to a portion of the String, \\\nWith Rust's `..` range syntax, if you want to start at index zero, you can drop the value before the two periods \\\nBy the same token, if your slice includes the last byte of the String, you can drop the trailing number. \n> Note: String slice range indices must occur at **valid UTF-8 character boundaries**. If you attempt to create a string slice in the middle of a multibyte character, your program will exit with an error.\n\n```rust\nfn first_word(s :&String) -> &str {\n let bytes = s.as_bytes();\n for(i, &item) in bytes.iter().enumerate() {\n if item == b' ' {\n return &s[..i];\n }\n }\n &s[..]\n}\n```\n\n### String Literals Are Slices\n```rust\nfn main() {\nlet s = \"Hello, world!\";\n}\n```\nThe type of s here is &str: it's a slice pointing to that specific point of the binary. \n\n### String Slices as Parameters\n- Pass &str as a parameter, you can receive parameters of type &String and &str at the same time\n```rust\nfn first_word(s: &String) -> &str\n```\nequivalent to\n```rust\nfn first_word(s: &str) -> &str\n```\n\n### other slices\narray slice\n```rust\nfn main() {\n let a = [1, 2, 3, 4, 5];\n let slice = &a[1..3];\n assert_eq!(slice, &[2, 3]);\n}\n```","slug":"rust/rust-03-ownership","published":1,"updated":"2023-05-01T13:17:32.602Z","comments":1,"layout":"post","photos":[],"link":"","_id":"clk1e4wpq000c6hsj11cxhldu","content":"
ownership rule
\n
Each value in Rust has an owner.
\n
There can only be one owner at a time.
\n
When the owner goes out of scope, the value will be dropped.
\n
\n
variable scope
1 2 3 4 5 6
fnmain() { { // s is not valid here, it’s not yet declared lets = "hello"; // s is valid from this point forward // do stuff with s } // this scope is now over, and s is no longer valid }
\n\n
Move
stack-only data: Copy trait
such as primitive type
\n
1 2 3 4
fnmain() { letx = 5; lety = x; }
\n
bind the value 5 to x; then make a copy of the value in x and bind it to y.
ptr, len, capacity is stored in stack, while string value is stored in heap When we assign s1 to s2, the String data is copied, meaning we copy the pointer, the length, and the capacity that are on the stack. We do not copy the data on the heap
If we do want to deeply copy the heap data of the String, not just the stack data, we can use a common method called clone.
\n
ownership and function
\n
Passing a value to a function will result in a move or copy of ownership
\n
difference between “stack” and “heap” variables: stack variables will be copied, and heap variables will be moved. When a variable containing heap data leaves the scope, its value will be cleared by the drop function, unless the ownership of the data is moved to another variable
fnmain() { lets = String::from("hello"); // s comes into scope takes_ownership(s); // s's value moves into the function... // ... and so is no longer valid here
letx = 5; // x comes into scope
makes_copy(x); // x would move into the function, // but i32 is Copy, so it's okay to still // use x afterward
} // Here, x goes out of scope, then s. But because s's value was moved, nothing // special happens.
fntakes_ownership(some_string: String) { // some_string comes into scope println!("{}", some_string); } // Here, some_string goes out of scope and `drop` is called. The backing // memory is freed.
fnmakes_copy(some_integer: i32) { // some_integer comes into scope println!("{}", some_integer); } // Here, some_integer goes out of scope. Nothing special happens.
fnmain() { lets1 = gives_ownership(); // gives_ownership moves its return // value into s1
lets2 = String::from("hello"); // s2 comes into scope
lets3 = takes_and_gives_back(s2); // s2 is moved into // takes_and_gives_back, which also // moves its return value into s3 } // Here, s3 goes out of scope and is dropped. s2 was moved, so nothing // happens. s1 goes out of scope and is dropped.
fngives_ownership() ->String { // gives_ownership will move its // return value into the function // that calls it
letsome_string = String::from("yours"); // some_string comes into scope
some_string // some_string is returned and // moves out to the calling // function }
// This function takes a String and returns one fntakes_and_gives_back(a_string: String) ->String { // a_string comes into // scope
a_string // a_string is returned and moves out to the calling function }
\n
\n
What if we want to let a function use a value but not take ownership? that’s reference
\n
\n
reference & borrow
\n
& means reference (borrow but not own), default immutable
\n
&mut a mutable reference, only one mutable reference allowed in same scope (avoid data racing)
\n
Multiple mutable references can be created non-simultaneously by creating a new scope
\n
Cannot have mutable and immutable references at the same time
fnmain() { letmut s = String::from("hello"); { lets1 = &mut s; } // r1 goes out of scope here, so we can make a new reference with no problems. lets2 = &mut s; }
fnmain() { letmut s = String::from("hello");
letr1 = &s; // no problem letr2 = &s; // no problem println!("{} and {}", r1, r2); // variables r1 and r2 will not be used after this point
letr3 = &mut s; // no problem println!("{}", r3);
println!{"{}",r1} // got problem with above mutable borrow }
\n
\n
reference as function arguments
1 2 3 4 5 6 7 8 9 10 11 12
fnmain() { lets1 = String::from("hello");
letlen = calculate_length(&s1);
println!("The length of '{}' is {}.", s1, len); }
fncalculate_length(s: &String) ->usize { // s is a reference to a String s.len() } // Here, s goes out of scope. But because it does not have ownership of what // it refers to, nothing happens.
\n
we pass &s1 into calculate_length and, in its definition, we take &String rather than String. These ampersands represent references, and they allow you to refer to some value without taking ownership of it. Because it does not own it, the value it points to will not be dropped when the reference stops being used. When functions have references as parameters instead of the actual values, we won’t need to return the values in order to give back ownership, because we never had ownership. We call the action of creating a reference borrowing.
A pointer refers to an address in memory, but the memory may have been freed and allocated for use by someone else
\n
rust,The compiler can guarantee that there will never be dangling references
1 2 3 4 5 6 7 8
fnmain() { letr = dangle(); } fndangle() -> &string { // dangle returns a reference to a String lets = String::from("hello"); // s is a new String &s // we return a reference to the String, s } // Here, s goes out of scope, and is dropped. Its memory goes away. // Danger
\nThe solution here is to return the String directly:
1 2 3 4 5 6 7 8
fnmain() { letstring = no_dangle(); }
fnno_dangle() ->String { lets = String::from("hello"); s }
\nThis works without any problems. Ownership is moved out, and nothing is deallocated.
\n
\n
slice
\n
Slices let you reference a contiguous sequence of elements in a collection rather than the whole collection. A slice is a kind of reference, so it does not have ownership.
\n
\n
string slice
1 2 3 4 5 6
fnmain() { letmut s = String::from("Hello world");
lethello = &s[0..5]; letworld = &s[6..11]; }
\n
Rather than a reference to the entire String, hello is a reference to a portion of the String, With Rust’s .. range syntax, if you want to start at index zero, you can drop the value before the two periods By the same token, if your slice includes the last byte of the String, you can drop the trailing number.
\n
\n
Note: String slice range indices must occur at valid UTF-8 character boundaries. If you attempt to create a string slice in the middle of a multibyte character, your program will exit with an error.
\n
\n
1 2 3 4 5 6 7 8 9
fnfirst_word(s :&String) -> &str { letbytes = s.as_bytes(); for(i, &item) in bytes.iter().enumerate() { if item == b' ' { return &s[..i]; } } &s[..] }
\n\n
String Literals Are Slices
1 2 3
fnmain() { lets = "Hello, world!"; }
\n
The type of s here is &str: it’s a slice pointing to that specific point of the binary.
\n
String Slices as Parameters
\n
Pass &str as a parameter, you can receive parameters of type &String and &str at the same time
When the owner goes out of scope, the value will be dropped.
\n
\n
variable scope
1 2 3 4 5 6
fnmain() { { // s is not valid here, it’s not yet declared lets = "hello"; // s is valid from this point forward // do stuff with s } // this scope is now over, and s is no longer valid }
\n\n
Move
stack-only data: Copy trait
such as primitive type
\n
1 2 3 4
fnmain() { letx = 5; lety = x; }
\n
bind the value 5 to x; then make a copy of the value in x and bind it to y.
ptr, len, capacity is stored in stack, while string value is stored in heap When we assign s1 to s2, the String data is copied, meaning we copy the pointer, the length, and the capacity that are on the stack. We do not copy the data on the heap
If we do want to deeply copy the heap data of the String, not just the stack data, we can use a common method called clone.
\n
ownership and function
\n
Passing a value to a function will result in a move or copy of ownership
\n
difference between “stack” and “heap” variables: stack variables will be copied, and heap variables will be moved. When a variable containing heap data leaves the scope, its value will be cleared by the drop function, unless the ownership of the data is moved to another variable
fnmain() { lets = String::from("hello"); // s comes into scope takes_ownership(s); // s's value moves into the function... // ... and so is no longer valid here
letx = 5; // x comes into scope
makes_copy(x); // x would move into the function, // but i32 is Copy, so it's okay to still // use x afterward
} // Here, x goes out of scope, then s. But because s's value was moved, nothing // special happens.
fntakes_ownership(some_string: String) { // some_string comes into scope println!("{}", some_string); } // Here, some_string goes out of scope and `drop` is called. The backing // memory is freed.
fnmakes_copy(some_integer: i32) { // some_integer comes into scope println!("{}", some_integer); } // Here, some_integer goes out of scope. Nothing special happens.
fnmain() { lets1 = gives_ownership(); // gives_ownership moves its return // value into s1
lets2 = String::from("hello"); // s2 comes into scope
lets3 = takes_and_gives_back(s2); // s2 is moved into // takes_and_gives_back, which also // moves its return value into s3 } // Here, s3 goes out of scope and is dropped. s2 was moved, so nothing // happens. s1 goes out of scope and is dropped.
fngives_ownership() ->String { // gives_ownership will move its // return value into the function // that calls it
letsome_string = String::from("yours"); // some_string comes into scope
some_string // some_string is returned and // moves out to the calling // function }
// This function takes a String and returns one fntakes_and_gives_back(a_string: String) ->String { // a_string comes into // scope
a_string // a_string is returned and moves out to the calling function }
\n
\n
What if we want to let a function use a value but not take ownership? that’s reference
\n
\n
reference & borrow
\n
& means reference (borrow but not own), default immutable
\n
&mut a mutable reference, only one mutable reference allowed in same scope (avoid data racing)
\n
Multiple mutable references can be created non-simultaneously by creating a new scope
\n
Cannot have mutable and immutable references at the same time
fnmain() { letmut s = String::from("hello"); { lets1 = &mut s; } // r1 goes out of scope here, so we can make a new reference with no problems. lets2 = &mut s; }
fnmain() { letmut s = String::from("hello");
letr1 = &s; // no problem letr2 = &s; // no problem println!("{} and {}", r1, r2); // variables r1 and r2 will not be used after this point
letr3 = &mut s; // no problem println!("{}", r3);
println!{"{}",r1} // got problem with above mutable borrow }
\n
\n
reference as function arguments
1 2 3 4 5 6 7 8 9 10 11 12
fnmain() { lets1 = String::from("hello");
letlen = calculate_length(&s1);
println!("The length of '{}' is {}.", s1, len); }
fncalculate_length(s: &String) ->usize { // s is a reference to a String s.len() } // Here, s goes out of scope. But because it does not have ownership of what // it refers to, nothing happens.
\n
we pass &s1 into calculate_length and, in its definition, we take &String rather than String. These ampersands represent references, and they allow you to refer to some value without taking ownership of it. Because it does not own it, the value it points to will not be dropped when the reference stops being used. When functions have references as parameters instead of the actual values, we won’t need to return the values in order to give back ownership, because we never had ownership. We call the action of creating a reference borrowing.
A pointer refers to an address in memory, but the memory may have been freed and allocated for use by someone else
\n
rust,The compiler can guarantee that there will never be dangling references
1 2 3 4 5 6 7 8
fnmain() { letr = dangle(); } fndangle() -> &string { // dangle returns a reference to a String lets = String::from("hello"); // s is a new String &s // we return a reference to the String, s } // Here, s goes out of scope, and is dropped. Its memory goes away. // Danger
\nThe solution here is to return the String directly:
1 2 3 4 5 6 7 8
fnmain() { letstring = no_dangle(); }
fnno_dangle() ->String { lets = String::from("hello"); s }
\nThis works without any problems. Ownership is moved out, and nothing is deallocated.
\n
\n
slice
\n
Slices let you reference a contiguous sequence of elements in a collection rather than the whole collection. A slice is a kind of reference, so it does not have ownership.
\n
\n
string slice
1 2 3 4 5 6
fnmain() { letmut s = String::from("Hello world");
lethello = &s[0..5]; letworld = &s[6..11]; }
\n
Rather than a reference to the entire String, hello is a reference to a portion of the String, With Rust’s .. range syntax, if you want to start at index zero, you can drop the value before the two periods By the same token, if your slice includes the last byte of the String, you can drop the trailing number.
\n
\n
Note: String slice range indices must occur at valid UTF-8 character boundaries. If you attempt to create a string slice in the middle of a multibyte character, your program will exit with an error.
\n
\n
1 2 3 4 5 6 7 8 9
fnfirst_word(s :&String) -> &str { letbytes = s.as_bytes(); for(i, &item) in bytes.iter().enumerate() { if item == b' ' { return &s[..i]; } } &s[..] }
\n\n
String Literals Are Slices
1 2 3
fnmain() { lets = "Hello, world!"; }
\n
The type of s here is &str: it’s a slice pointing to that specific point of the binary.
\n
String Slices as Parameters
\n
Pass &str as a parameter, you can receive parameters of type &String and &str at the same time
"},{"title":"rust lifetime","date":"2022-10-18T13:33:26.000Z","_content":"\n## lifetime\n- Every reference in Rust has its own lifecycle\n- most of the time, Rust's lifetime is implicit and can be inferred\n- There are two types of life cycle: input life cycle and output life cycle\n- 'static is a special life cycle annotation\n### Example of lifetime out of scope\n```rust\nfn main() {\n let mut x;\n {\n let y = String::from(\"hello\");\n // x = y; // this is allowed\n x = &y; // not allowed. borrowed value (y) does not live long enough\n }\n println!(\"Str:{}\", x);\n}\n```\n\n### lifetime checker\nRust compiler's borrow checker to determine whether a borrow is legal\n```rust\n// If it returns a reference value, no matter how simple your function is written, it will always report an error `missing lifetime specifier.`\nfn longest(x:&str, y:&str) -> &str { /// this function's return type contains a borrowed value, but the signature does not say whether it is borrowed from `x` or `y`\n if x.len() > y.len() {\n x\n }else{\n y\n }\n}\n```\nlet's find out why it is such case\n```rust\nfn main() {\n // variable to hold the result value\n let long_str; \n\n let x = \"abc\".to_string();\n {\n let y = \"bbccd\".to_string();\n long_str = longest(x.as_str(), y.as_str());\n }\n // if x.len() > y.len() then it is OK,the long_str variable will hole x; if not, long_str supposed tohold y, however, y has a smaller scope than x, long_str will hold to a dropped value\n println!(\"Longest str: {}\", long_str);\n}\n\n```\nHence, we need lifetime annotation `'`\n```rust\nfn longest<'a>(x:&'a str, y:&'a str) -> &'a str {\n if x.len() > y.len() {\n x\n }else{\n y\n }\n}\n```\n\n### deeper understanding\n- When returning a reference value from a function, the lifetime of the return type needs to match the lifetime of one of the parameters\n\n### Struct lifetime annotation\n```rust\nfn main() {\n let info = String::from(\"File not found.\");\n // 存放结果值的变量\n let exc = ImportantExcepiton {\n part: info.as_str()\n };\n\n println!(\"{:?}\", exc);\n}\n#[derive(Debug)]\nstruct ImportantExcepiton<'a> {\n part: &'a str,\n}\n```\n- lifetime of the field `part` must be longer than struct\n\n### Lifetime Elision\nIn order to make common patterns more ergonomic, Rust allows lifetimes to be elided in function signatures.\nElision rules are as follows:\n- Each elided lifetime in input position becomes a distinct lifetime parameter.\n- If there is exactly one input lifetime position (elided or not), that lifetime is assigned to all elided output lifetimes.\n- If there are multiple input lifetime positions, but one of them is &self or &mut self, the lifetime of self is assigned to all elided output lifetimes.\n- Otherwise, it is an error to elide an output lifetime.\n\n### struct lifetime annotation\n```rust\n\nfn main() {\n let info = String::from(\"File not found.\");\n let exc = ImportantExcepiton {\n part: info.as_str()\n };\n\n println!(\"{:?}\", exc);\n}\n#[derive(Debug)]\nstruct ImportantExcepiton <'a>{\n part: &'a str,\n}\n\n// the first 'a is decraration, the second is usage\nimpl<'a> ImportantExcepiton <'a> {\n // in return value, 'a is omitted according to Lifetime Elision rule\n fn callname(&self ) -> &str{\n self.part\n }\n}\n```\n\n### 'static\n'static is a special lifetime that takes up the duration of the entire program, for example all string literals have a 'static lifetime","source":"_posts/rust/rust-04-lifetime.md","raw":"---\ntitle: rust lifetime\ndate: 2022-10-18 21:33:26\ntags: [rust]\n---\n\n## lifetime\n- Every reference in Rust has its own lifecycle\n- most of the time, Rust's lifetime is implicit and can be inferred\n- There are two types of life cycle: input life cycle and output life cycle\n- 'static is a special life cycle annotation\n### Example of lifetime out of scope\n```rust\nfn main() {\n let mut x;\n {\n let y = String::from(\"hello\");\n // x = y; // this is allowed\n x = &y; // not allowed. borrowed value (y) does not live long enough\n }\n println!(\"Str:{}\", x);\n}\n```\n\n### lifetime checker\nRust compiler's borrow checker to determine whether a borrow is legal\n```rust\n// If it returns a reference value, no matter how simple your function is written, it will always report an error `missing lifetime specifier.`\nfn longest(x:&str, y:&str) -> &str { /// this function's return type contains a borrowed value, but the signature does not say whether it is borrowed from `x` or `y`\n if x.len() > y.len() {\n x\n }else{\n y\n }\n}\n```\nlet's find out why it is such case\n```rust\nfn main() {\n // variable to hold the result value\n let long_str; \n\n let x = \"abc\".to_string();\n {\n let y = \"bbccd\".to_string();\n long_str = longest(x.as_str(), y.as_str());\n }\n // if x.len() > y.len() then it is OK,the long_str variable will hole x; if not, long_str supposed tohold y, however, y has a smaller scope than x, long_str will hold to a dropped value\n println!(\"Longest str: {}\", long_str);\n}\n\n```\nHence, we need lifetime annotation `'`\n```rust\nfn longest<'a>(x:&'a str, y:&'a str) -> &'a str {\n if x.len() > y.len() {\n x\n }else{\n y\n }\n}\n```\n\n### deeper understanding\n- When returning a reference value from a function, the lifetime of the return type needs to match the lifetime of one of the parameters\n\n### Struct lifetime annotation\n```rust\nfn main() {\n let info = String::from(\"File not found.\");\n // 存放结果值的变量\n let exc = ImportantExcepiton {\n part: info.as_str()\n };\n\n println!(\"{:?}\", exc);\n}\n#[derive(Debug)]\nstruct ImportantExcepiton<'a> {\n part: &'a str,\n}\n```\n- lifetime of the field `part` must be longer than struct\n\n### Lifetime Elision\nIn order to make common patterns more ergonomic, Rust allows lifetimes to be elided in function signatures.\nElision rules are as follows:\n- Each elided lifetime in input position becomes a distinct lifetime parameter.\n- If there is exactly one input lifetime position (elided or not), that lifetime is assigned to all elided output lifetimes.\n- If there are multiple input lifetime positions, but one of them is &self or &mut self, the lifetime of self is assigned to all elided output lifetimes.\n- Otherwise, it is an error to elide an output lifetime.\n\n### struct lifetime annotation\n```rust\n\nfn main() {\n let info = String::from(\"File not found.\");\n let exc = ImportantExcepiton {\n part: info.as_str()\n };\n\n println!(\"{:?}\", exc);\n}\n#[derive(Debug)]\nstruct ImportantExcepiton <'a>{\n part: &'a str,\n}\n\n// the first 'a is decraration, the second is usage\nimpl<'a> ImportantExcepiton <'a> {\n // in return value, 'a is omitted according to Lifetime Elision rule\n fn callname(&self ) -> &str{\n self.part\n }\n}\n```\n\n### 'static\n'static is a special lifetime that takes up the duration of the entire program, for example all string literals have a 'static lifetime","slug":"rust/rust-04-lifetime","published":1,"updated":"2023-05-01T14:08:49.387Z","comments":1,"layout":"post","photos":[],"link":"","_id":"clk1e4wpr000f6hsj2rgy3f9c","content":"
lifetime
\n
Every reference in Rust has its own lifecycle
\n
most of the time, Rust’s lifetime is implicit and can be inferred
\n
There are two types of life cycle: input life cycle and output life cycle
\n
‘static is a special life cycle annotation
\n
\n
Example of lifetime out of scope
1 2 3 4 5 6 7 8 9
fnmain() { letmut x; { lety = String::from("hello"); // x = y; // this is allowed x = &y; // not allowed. borrowed value (y) does not live long enough } println!("Str:{}", x); }
\n\n
lifetime checker
Rust compiler’s borrow checker to determine whether a borrow is legal
\n
1 2 3 4 5 6 7 8
// If it returns a reference value, no matter how simple your function is written, it will always report an error `missing lifetime specifier.` fnlongest(x:&str, y:&str) -> &str { /// this function's return type contains a borrowed value, but the signature does not say whether it is borrowed from `x` or `y` if x.len() > y.len() { x }else{ y } }
\n
let’s find out why it is such case
\n
1 2 3 4 5 6 7 8 9 10 11 12 13
fnmain() { // variable to hold the result value letlong_str;
letx = "abc".to_string(); { lety = "bbccd".to_string(); long_str = longest(x.as_str(), y.as_str()); } // if x.len() > y.len() then it is OK,the long_str variable will hole x; if not, long_str supposed tohold y, however, y has a smaller scope than x, long_str will hold to a dropped value println!("Longest str: {}", long_str); }
\n
Hence, we need lifetime annotation '
\n
1 2 3 4 5 6 7
fnlongest<'a>(x:&'astr, y:&'astr) -> &'astr { if x.len() > y.len() { x }else{ y } }
\n\n
deeper understanding
\n
When returning a reference value from a function, the lifetime of the return type needs to match the lifetime of one of the parameters
lifetime of the field part must be longer than struct
\n
\n
Lifetime Elision
In order to make common patterns more ergonomic, Rust allows lifetimes to be elided in function signatures. Elision rules are as follows:
\n
\n
Each elided lifetime in input position becomes a distinct lifetime parameter.
\n
If there is exactly one input lifetime position (elided or not), that lifetime is assigned to all elided output lifetimes.
\n
If there are multiple input lifetime positions, but one of them is &self or &mut self, the lifetime of self is assigned to all elided output lifetimes.
\n
Otherwise, it is an error to elide an output lifetime.
// the first 'a is decraration, the second is usage impl<'a> ImportantExcepiton <'a> { // in return value, 'a is omitted according to Lifetime Elision rule fncallname(&self ) -> &str{ self.part } }
\n\n
‘static
‘static is a special lifetime that takes up the duration of the entire program, for example all string literals have a ‘static lifetime
\n","site":{"data":{}},"excerpt":"","more":"
lifetime
\n
Every reference in Rust has its own lifecycle
\n
most of the time, Rust’s lifetime is implicit and can be inferred
\n
There are two types of life cycle: input life cycle and output life cycle
\n
‘static is a special life cycle annotation
\n
\n
Example of lifetime out of scope
1 2 3 4 5 6 7 8 9
fnmain() { letmut x; { lety = String::from("hello"); // x = y; // this is allowed x = &y; // not allowed. borrowed value (y) does not live long enough } println!("Str:{}", x); }
\n\n
lifetime checker
Rust compiler’s borrow checker to determine whether a borrow is legal
\n
1 2 3 4 5 6 7 8
// If it returns a reference value, no matter how simple your function is written, it will always report an error `missing lifetime specifier.` fnlongest(x:&str, y:&str) -> &str { /// this function's return type contains a borrowed value, but the signature does not say whether it is borrowed from `x` or `y` if x.len() > y.len() { x }else{ y } }
\n
let’s find out why it is such case
\n
1 2 3 4 5 6 7 8 9 10 11 12 13
fnmain() { // variable to hold the result value letlong_str;
letx = "abc".to_string(); { lety = "bbccd".to_string(); long_str = longest(x.as_str(), y.as_str()); } // if x.len() > y.len() then it is OK,the long_str variable will hole x; if not, long_str supposed tohold y, however, y has a smaller scope than x, long_str will hold to a dropped value println!("Longest str: {}", long_str); }
\n
Hence, we need lifetime annotation '
\n
1 2 3 4 5 6 7
fnlongest<'a>(x:&'astr, y:&'astr) -> &'astr { if x.len() > y.len() { x }else{ y } }
\n\n
deeper understanding
\n
When returning a reference value from a function, the lifetime of the return type needs to match the lifetime of one of the parameters
lifetime of the field part must be longer than struct
\n
\n
Lifetime Elision
In order to make common patterns more ergonomic, Rust allows lifetimes to be elided in function signatures. Elision rules are as follows:
\n
\n
Each elided lifetime in input position becomes a distinct lifetime parameter.
\n
If there is exactly one input lifetime position (elided or not), that lifetime is assigned to all elided output lifetimes.
\n
If there are multiple input lifetime positions, but one of them is &self or &mut self, the lifetime of self is assigned to all elided output lifetimes.
\n
Otherwise, it is an error to elide an output lifetime.
// the first 'a is decraration, the second is usage impl<'a> ImportantExcepiton <'a> { // in return value, 'a is omitted according to Lifetime Elision rule fncallname(&self ) -> &str{ self.part } }
\n\n
‘static
‘static is a special lifetime that takes up the duration of the entire program, for example all string literals have a ‘static lifetime
\n"},{"title":"rust basics","date":"2022-10-04T07:55:04.000Z","_content":"\n## frequently used cmd\n```\nrustc [filename].rs\ncargo new [project_name]\ncargo build [--release]\ncargo run [--release]\ncargo check # check whether compile success, no executible output\n```\n\n## data type\n\n### integer\n- i8,i16,i32,i64,i128,isize,u8,u16,u32,u64,u128,usize,etc\n- isize, usize indicates that the type is determined by the architecture of the computer. For example, on a 32 bit target, this is 4 bytes and on a 64 bit target, this is 8 bytes.\n- 0x: hex,0o Octal,0b binary,starting with b: byte (u8 only)\n\n| Number Literals | Example |\n| ----------- | ----------- |\n| Decimal | 98_222 |\n| Hex | 0xff |\n| Octal | 0o77 |\n| Binary | 0b1111_0000 |\n| Byte(u8 only) | b'A' |\n\n### Tuple\n- The length of Tuple is fixed, and the length cannot be changed once declared\n```rust\nfn main() {\n // tuple could be declared as mut\n let mut tuple_1 = (\"Hello\", 39, \"Years\");\n let tuple_2:(i32, &str ) = (1983, \"since.\");\n tuple_1.0 = \"Hi\";\n println!(\"{} {} {}\", tuple_1.0, tuple_1.1, tuple_1.2);\n // destructure\n let (a,b) = tuple_2;\n println!(\"{} {}\", a, b);\n}\n```\n\n### array\n- arrays in Rust have a fixed length.\n- Vector is similar to an array, it is provided by the standard library, and its length can be changed\n\n```rust\nfn main() {\n\n let arr_test:[u8; 3] = [1,2,3];\n println!(\"Number is {},{},{}\", arr_test[0],arr_test[1],arr_test[2]);\n\n let arr_test = [\"I\",\"love\",\"you\"];\n println!(\"You said : {} {} {}\", arr_test[0],arr_test[1],arr_test[2]);\n\n let arr_test = [1;3]; \n println!(\"Call Num : {}&{}&{}\", arr_test[0],arr_test[1],arr_test[2]);\n}\n```\n\n\n\n### String\n- Basic data types are stored on the stack, but the String type is stored on the heap\n```rust\nlet s = String::from(\"hello\");\n```\n- push_str(): append a str slice a string\n- push(): appends a single character to a String\n```rust\nfn main() { \n let mut data = String::from(\"andy\");\n data.push_str(\" is stronger\");\n data.push('!');\n}\n```\n- + operator, chaining strings. the left side of the + operator is the ownership of the string, and the right side is the string slice\n- String is actually a wrapper for Vec, so the length can be measured by the len() method, but note that Len() is not length of character, but byte len\n- String iteration\n```rust\nfn main() { \n let mut data = String::from(\"andy\");\n data.push_str(\" is stronger\");\n data.push('!');\n\n for i in data.bytes() {\n ///\n }\n\n for i in data.chars() {\n ///\n }\n}\n```\n\n### Vector\n- Vector is like any other struct. When Vector leaves the scope, the variable value is cleaned up, and all its elements are also cleaned up.\n```rust\nfn main() {\n let vec: Vec = Vec::new();\n let vec2: Vec = vec![3,4,5] // create vector by macro\n for i in vec2 {\n println!(\"Vector value is : {}\", i);\n }\n}\n```\n\n### HashMap\n- HashMap is not preloaded, so it needs to be included `use std::collections::HashMap`\n```rust\nuse std::collections::HashMap;\nfn main() {\n let keys = vec![\"andy\".to_string(), \"cliff\".to_string()] ;\n let ages = vec![38, 26];\n let map :HashMap<_,_> = keys.iter().zip(ages.iter()).collect();\n println!(\"{:?}\", map); /// print {\"andy\": 38, \"cliff\": 26}\n}\n```\n#### HashMap ownership\n- For types that implement the Copy trait (such as i32), the value will be copied into the HashMap\n- For values with ownership, such as (String), the value will be moved and ownership will be given to HashMap\n- If a reference to a value is inserted into the HashMap, the value itself does not move\n\n#### HashMap iteration\n```rust\nuse std::collections::HashMap;\n\nfn main() { \n let name = \"andy\".to_string();\n let age = 36;\n let mut map = HashMap::new();\n map.insert(name, age);\n map.insert(String::from(\"cliff\"), 26);\n println!(\"{:?}\", &map);\n for (k, v) in map {\n println!(\"{} age {}\", k, v);\n } /// cliff age 26\n /// andy age 36\n}\n```\n#### update\n```rust\nuse std::collections::HashMap;\n\nfn main() { \n let name = \"andy\".to_string();\n let age = 36;\n let mut map = HashMap::new();\n map.insert(name, age);\n map.insert(String::from(\"cliff\"), 26);\n\n let result = map.entry(\"bob\".to_string());\n println!(\"{:?}\", result); /// Entry(VacantEntry(\"bob\"))\n\n let result = map.entry(\"andy\".to_string());\n println!(\"{:?}\", result); /// Entry(OccupiedEntry { key: \"andy\", value: 36, .. })\n\n map.entry(\"bob\".to_string()).or_insert(28);\n map.entry(\"cliff\".to_string()).or_insert(0);\n}\n```\n\n## control flow\n- if\n```rust\nfn main() {\n let condition = 1;\n let x = if condition == 1 { \"A\" } else { \"B\" };\n println!(\"Result x = {}\" , x) ;\n}\n```\n- loop\n```rust\nfn main() {\n let mut condition = 0;\n\n let result = 'outer: loop { // 'outer is label\n 'inner: loop {\n condition += 1;\n if 3 == condition {\n break 'outer 3 * condition; // break outer loop\n }\n }\n };\n println!(\"Loop result is : {}\", result); /// Loop result is : 9\n}\n\n```\n- rot\n```rust\nfn main() {\n let arr = [3,2,3];\n for num in arr.iter() {\n println!(\"For value is {}\", num);\n }\n}\n```\n\n## Range iterator\n- Range\n```rust\nfn main() {\n for number in (1..=3) {\n println!(\"Number A is {}\", number ); /// 1,2,3\n }\n \n for number in (1..=3).rev() { /// rev means reverse,\n println!(\"Number B is {}\", number ); /// 3,2,1\n }\n}\n\n```\n\n## struct\n- If struct is declared mutable then all fields in the instance are mutable\n### tuple struct\n```rust\nstruct Color(i32,i32,i32);\nlet black = Color(0,0,0);\n```\n### Unit-Like struct\n```rust\nstruct Man {};\n```\n### struct method\n```rust\n\nfn main() {\n let rec = Rectangle {\n width: 30,\n height: 50,\n };\n\n let result = rec.area(); \n println!(\"rectangle:{:?},area is:{}\", rec, result);\n}\n\n\n#[derive(Debug)]\nstruct Rectangle {\n width: u32,\n height: u32,\n}\n\nimpl Rectangle {\n fn area(&self) -> u32{\n self.width * self.height\n }\n}\n\n```\n### associative func(similar to static method)\n- You can define a function that does not take `self` as the first parameter in the impl block. This form is called an associated function, and the calling method is similar to `String::from()`\n```rust\nimpl Rectangle {\n fn create_square(width: u32) -> Rectangle {\n Rectangle {\n width,\n height: width,\n }\n }\n}\n```\n \n## enum\n```rust\nenum Ip {\n V4,\n V6,\n}\n\nenum IpAddr {\n V4(String),\n V6(String),\n}\n``` \n\n## match\n- match must exhaust all possibilities\n- If there are too many matchings, you can also use \"_\" for wildcarding, but note that \"_\" must be placed at the end\n```rust\nenum Color {\n Red,\n Yellow,\n Blue,\n}\nenum ColorWithVal {\n Red(u8,u8,u8),\n Yellow(u8,u8,u8),\n Blue(u8,u8,u8),\n}\nfn main(){\n let colour = Color::Blue;\n match colour {\n Color::Red => {\n println!(\"Red colour.\");\n },\n _ => {\n println!(\"Other colour.\");\n }\n }\n\n let colour = ColorWithVal::Red(222,111,22);\n match colour {\n ColorWithVal::Red(r,g,b) => {\n println!(\"Red colour. {},{},{}\", r,g,b);\n },\n _ => {\n println!(\"Other colour.\");\n }\n }\n}\n```\n\n## if let\n```rust\nfn main(){\n let colour = Color::Red(Some(222),Some(222),Some(222));\n\n if let Color::Red(r,g,b) = colour {\n println!(\"Red colour. {:?},{:?},{:?}\", r,g,b);\n } else {\n println!(\"Other colour.\");\n }\n}\n```\n\n## Result\n- Recoverable err via Result, non-recoverable via panic!\n- upon panic!, the program will expand an error message, unwind, clean up the call stack (Stack) and finally exit the program\n- You can set panic = 'abort' in Cargo.toml to terminate the cleaning of the call stack\n```rust\n[profile.release]\npanic='abort'\n```\n- RUST_BACKTRACE = 1 prints detailed error messages in the stack\n```rust\nuse std::fs::File;\nfn main() { \n let fp = File::open(\"hello.txt\");\n let file = match fp {\n Ok(file)=> {\n file\n },\n Err(error) => panic!(\"file not found {:?} \", error),\n };\n}\n```\n\n```rust\nuse std::{fs::File, io::ErrorKind};\nfn main() { \n let fp = File::open(\"hello.txt\");\n let file = match fp {\n Ok(file)=> {\n file\n },\n Err(error) => {\n match error.kind() {\n ErrorKind::NotFound => {\n match File::create(\"hello.txt\") {\n Ok(file) => {\n file\n },\n Err(err) => {\n panic!(\"file create error:{:?}\", &err);\n },\n }\n },\n oe => panic!(\"other error {:?}\", oe),\n }\n } ,\n };\n}\n```\n```rust\nuse std::{fs::File, io::ErrorKind};\nfn main() { \n let file = File::open(\"hello.txt\").unwrap_or_else(|err| {\n if err.kind() == ErrorKind::NotFound {\n File::create(\"hello.txt\").unwrap_or_else(|err|{\n panic!(\"error:{:?}\", err);\n })\n }else{\n panic!(\"other error:{:?}\", err);\n }\n });\n}\n```\n### unwrap && expect\n- If do not want to deal with Err, can use unwarp() method. If result is Ok(val), return val. If Err, then call the panic! macro.\n- expect can specify what the error message is, which is easier to debug\n\n### The question mark operator, ?\nWhen writing code that calls many functions that return the Result type, the error handling can be tedious. The question mark operator, ?, hides some of the boilerplate of propagating errors up the call stack.\n```rust\nlet mut file = File::create(\"my_best_friends.txt\")?;\n```\n\n## generic\n```rust\n#[derive(Debug)]\nstruct Point {\n x : T,\n y : U,\n}\nimpl Point {\n fn mixup(self, other: Point) -> Point {\n Point{x: self.x , y: other.y, }\n }\n}\n```\n\n## trait\n### definition\n```rust\npub trait Summary {\n fn summarize(&self) -> String {\n \"... more\".to_string() /// default \n }\n}\npub struct Tweet {\n user_name :String,\n replay_count :u32,\n like_count :u32,\n}\nimpl Tweet {\n fn like(&mut self) {\n self.like_count += 1;\n }\n}\n\nimpl Summary for Tweet {\n fn summarize(&self) -> String {\n format!(\"{} like count :{} , replay count :{}\", &self.user_name, &self.replay_count, &self.like_count)\n }\n}\n```\n\n### trait as arguments\n```rust\nfn notify_msg (info: T) {\n println!(\"summary : {}\", info.summarize() );\n}\nfn notify_msg (info: impl Summary + Display) {\n println!(\"summary : {}\", info.summarize() );\n}\nfn notify_msg (info: T) \nwhere \n T: Summary + Display,\n{\n println!(\"summary : {}\", info.summarize() );\n println!(\"display implement info : {}\", info);\n}\n```\n### trait as return\n- impl Trait can only return the same type, if it returns a different type, even if the Trait is implemented, an error will be reported\n\n## references\n- [the rust programming language](https://doc.rust-lang.org/book/)\n- [mooc course](https://time.geekbang.org/course/intro/100060601?tab=catalog)\n- [bilibili tutorial](https://www.bilibili.com/video/BV1hp4y1k7SV?p=50&spm_id_from=pageDriver)\n- [jianshu notes](https://www.jianshu.com/p/30d917790298)","source":"_posts/rust/rust-02-basics.md","raw":"---\ntitle: rust basics\ndate: 2022-10-04 15:55:04\ntags: [rust]\n---\n\n## frequently used cmd\n```\nrustc [filename].rs\ncargo new [project_name]\ncargo build [--release]\ncargo run [--release]\ncargo check # check whether compile success, no executible output\n```\n\n## data type\n\n### integer\n- i8,i16,i32,i64,i128,isize,u8,u16,u32,u64,u128,usize,etc\n- isize, usize indicates that the type is determined by the architecture of the computer. For example, on a 32 bit target, this is 4 bytes and on a 64 bit target, this is 8 bytes.\n- 0x: hex,0o Octal,0b binary,starting with b: byte (u8 only)\n\n| Number Literals | Example |\n| ----------- | ----------- |\n| Decimal | 98_222 |\n| Hex | 0xff |\n| Octal | 0o77 |\n| Binary | 0b1111_0000 |\n| Byte(u8 only) | b'A' |\n\n### Tuple\n- The length of Tuple is fixed, and the length cannot be changed once declared\n```rust\nfn main() {\n // tuple could be declared as mut\n let mut tuple_1 = (\"Hello\", 39, \"Years\");\n let tuple_2:(i32, &str ) = (1983, \"since.\");\n tuple_1.0 = \"Hi\";\n println!(\"{} {} {}\", tuple_1.0, tuple_1.1, tuple_1.2);\n // destructure\n let (a,b) = tuple_2;\n println!(\"{} {}\", a, b);\n}\n```\n\n### array\n- arrays in Rust have a fixed length.\n- Vector is similar to an array, it is provided by the standard library, and its length can be changed\n\n```rust\nfn main() {\n\n let arr_test:[u8; 3] = [1,2,3];\n println!(\"Number is {},{},{}\", arr_test[0],arr_test[1],arr_test[2]);\n\n let arr_test = [\"I\",\"love\",\"you\"];\n println!(\"You said : {} {} {}\", arr_test[0],arr_test[1],arr_test[2]);\n\n let arr_test = [1;3]; \n println!(\"Call Num : {}&{}&{}\", arr_test[0],arr_test[1],arr_test[2]);\n}\n```\n\n\n\n### String\n- Basic data types are stored on the stack, but the String type is stored on the heap\n```rust\nlet s = String::from(\"hello\");\n```\n- push_str(): append a str slice a string\n- push(): appends a single character to a String\n```rust\nfn main() { \n let mut data = String::from(\"andy\");\n data.push_str(\" is stronger\");\n data.push('!');\n}\n```\n- + operator, chaining strings. the left side of the + operator is the ownership of the string, and the right side is the string slice\n- String is actually a wrapper for Vec, so the length can be measured by the len() method, but note that Len() is not length of character, but byte len\n- String iteration\n```rust\nfn main() { \n let mut data = String::from(\"andy\");\n data.push_str(\" is stronger\");\n data.push('!');\n\n for i in data.bytes() {\n ///\n }\n\n for i in data.chars() {\n ///\n }\n}\n```\n\n### Vector\n- Vector is like any other struct. When Vector leaves the scope, the variable value is cleaned up, and all its elements are also cleaned up.\n```rust\nfn main() {\n let vec: Vec = Vec::new();\n let vec2: Vec = vec![3,4,5] // create vector by macro\n for i in vec2 {\n println!(\"Vector value is : {}\", i);\n }\n}\n```\n\n### HashMap\n- HashMap is not preloaded, so it needs to be included `use std::collections::HashMap`\n```rust\nuse std::collections::HashMap;\nfn main() {\n let keys = vec![\"andy\".to_string(), \"cliff\".to_string()] ;\n let ages = vec![38, 26];\n let map :HashMap<_,_> = keys.iter().zip(ages.iter()).collect();\n println!(\"{:?}\", map); /// print {\"andy\": 38, \"cliff\": 26}\n}\n```\n#### HashMap ownership\n- For types that implement the Copy trait (such as i32), the value will be copied into the HashMap\n- For values with ownership, such as (String), the value will be moved and ownership will be given to HashMap\n- If a reference to a value is inserted into the HashMap, the value itself does not move\n\n#### HashMap iteration\n```rust\nuse std::collections::HashMap;\n\nfn main() { \n let name = \"andy\".to_string();\n let age = 36;\n let mut map = HashMap::new();\n map.insert(name, age);\n map.insert(String::from(\"cliff\"), 26);\n println!(\"{:?}\", &map);\n for (k, v) in map {\n println!(\"{} age {}\", k, v);\n } /// cliff age 26\n /// andy age 36\n}\n```\n#### update\n```rust\nuse std::collections::HashMap;\n\nfn main() { \n let name = \"andy\".to_string();\n let age = 36;\n let mut map = HashMap::new();\n map.insert(name, age);\n map.insert(String::from(\"cliff\"), 26);\n\n let result = map.entry(\"bob\".to_string());\n println!(\"{:?}\", result); /// Entry(VacantEntry(\"bob\"))\n\n let result = map.entry(\"andy\".to_string());\n println!(\"{:?}\", result); /// Entry(OccupiedEntry { key: \"andy\", value: 36, .. })\n\n map.entry(\"bob\".to_string()).or_insert(28);\n map.entry(\"cliff\".to_string()).or_insert(0);\n}\n```\n\n## control flow\n- if\n```rust\nfn main() {\n let condition = 1;\n let x = if condition == 1 { \"A\" } else { \"B\" };\n println!(\"Result x = {}\" , x) ;\n}\n```\n- loop\n```rust\nfn main() {\n let mut condition = 0;\n\n let result = 'outer: loop { // 'outer is label\n 'inner: loop {\n condition += 1;\n if 3 == condition {\n break 'outer 3 * condition; // break outer loop\n }\n }\n };\n println!(\"Loop result is : {}\", result); /// Loop result is : 9\n}\n\n```\n- rot\n```rust\nfn main() {\n let arr = [3,2,3];\n for num in arr.iter() {\n println!(\"For value is {}\", num);\n }\n}\n```\n\n## Range iterator\n- Range\n```rust\nfn main() {\n for number in (1..=3) {\n println!(\"Number A is {}\", number ); /// 1,2,3\n }\n \n for number in (1..=3).rev() { /// rev means reverse,\n println!(\"Number B is {}\", number ); /// 3,2,1\n }\n}\n\n```\n\n## struct\n- If struct is declared mutable then all fields in the instance are mutable\n### tuple struct\n```rust\nstruct Color(i32,i32,i32);\nlet black = Color(0,0,0);\n```\n### Unit-Like struct\n```rust\nstruct Man {};\n```\n### struct method\n```rust\n\nfn main() {\n let rec = Rectangle {\n width: 30,\n height: 50,\n };\n\n let result = rec.area(); \n println!(\"rectangle:{:?},area is:{}\", rec, result);\n}\n\n\n#[derive(Debug)]\nstruct Rectangle {\n width: u32,\n height: u32,\n}\n\nimpl Rectangle {\n fn area(&self) -> u32{\n self.width * self.height\n }\n}\n\n```\n### associative func(similar to static method)\n- You can define a function that does not take `self` as the first parameter in the impl block. This form is called an associated function, and the calling method is similar to `String::from()`\n```rust\nimpl Rectangle {\n fn create_square(width: u32) -> Rectangle {\n Rectangle {\n width,\n height: width,\n }\n }\n}\n```\n \n## enum\n```rust\nenum Ip {\n V4,\n V6,\n}\n\nenum IpAddr {\n V4(String),\n V6(String),\n}\n``` \n\n## match\n- match must exhaust all possibilities\n- If there are too many matchings, you can also use \"_\" for wildcarding, but note that \"_\" must be placed at the end\n```rust\nenum Color {\n Red,\n Yellow,\n Blue,\n}\nenum ColorWithVal {\n Red(u8,u8,u8),\n Yellow(u8,u8,u8),\n Blue(u8,u8,u8),\n}\nfn main(){\n let colour = Color::Blue;\n match colour {\n Color::Red => {\n println!(\"Red colour.\");\n },\n _ => {\n println!(\"Other colour.\");\n }\n }\n\n let colour = ColorWithVal::Red(222,111,22);\n match colour {\n ColorWithVal::Red(r,g,b) => {\n println!(\"Red colour. {},{},{}\", r,g,b);\n },\n _ => {\n println!(\"Other colour.\");\n }\n }\n}\n```\n\n## if let\n```rust\nfn main(){\n let colour = Color::Red(Some(222),Some(222),Some(222));\n\n if let Color::Red(r,g,b) = colour {\n println!(\"Red colour. {:?},{:?},{:?}\", r,g,b);\n } else {\n println!(\"Other colour.\");\n }\n}\n```\n\n## Result\n- Recoverable err via Result, non-recoverable via panic!\n- upon panic!, the program will expand an error message, unwind, clean up the call stack (Stack) and finally exit the program\n- You can set panic = 'abort' in Cargo.toml to terminate the cleaning of the call stack\n```rust\n[profile.release]\npanic='abort'\n```\n- RUST_BACKTRACE = 1 prints detailed error messages in the stack\n```rust\nuse std::fs::File;\nfn main() { \n let fp = File::open(\"hello.txt\");\n let file = match fp {\n Ok(file)=> {\n file\n },\n Err(error) => panic!(\"file not found {:?} \", error),\n };\n}\n```\n\n```rust\nuse std::{fs::File, io::ErrorKind};\nfn main() { \n let fp = File::open(\"hello.txt\");\n let file = match fp {\n Ok(file)=> {\n file\n },\n Err(error) => {\n match error.kind() {\n ErrorKind::NotFound => {\n match File::create(\"hello.txt\") {\n Ok(file) => {\n file\n },\n Err(err) => {\n panic!(\"file create error:{:?}\", &err);\n },\n }\n },\n oe => panic!(\"other error {:?}\", oe),\n }\n } ,\n };\n}\n```\n```rust\nuse std::{fs::File, io::ErrorKind};\nfn main() { \n let file = File::open(\"hello.txt\").unwrap_or_else(|err| {\n if err.kind() == ErrorKind::NotFound {\n File::create(\"hello.txt\").unwrap_or_else(|err|{\n panic!(\"error:{:?}\", err);\n })\n }else{\n panic!(\"other error:{:?}\", err);\n }\n });\n}\n```\n### unwrap && expect\n- If do not want to deal with Err, can use unwarp() method. If result is Ok(val), return val. If Err, then call the panic! macro.\n- expect can specify what the error message is, which is easier to debug\n\n### The question mark operator, ?\nWhen writing code that calls many functions that return the Result type, the error handling can be tedious. The question mark operator, ?, hides some of the boilerplate of propagating errors up the call stack.\n```rust\nlet mut file = File::create(\"my_best_friends.txt\")?;\n```\n\n## generic\n```rust\n#[derive(Debug)]\nstruct Point {\n x : T,\n y : U,\n}\nimpl Point {\n fn mixup(self, other: Point) -> Point {\n Point{x: self.x , y: other.y, }\n }\n}\n```\n\n## trait\n### definition\n```rust\npub trait Summary {\n fn summarize(&self) -> String {\n \"... more\".to_string() /// default \n }\n}\npub struct Tweet {\n user_name :String,\n replay_count :u32,\n like_count :u32,\n}\nimpl Tweet {\n fn like(&mut self) {\n self.like_count += 1;\n }\n}\n\nimpl Summary for Tweet {\n fn summarize(&self) -> String {\n format!(\"{} like count :{} , replay count :{}\", &self.user_name, &self.replay_count, &self.like_count)\n }\n}\n```\n\n### trait as arguments\n```rust\nfn notify_msg (info: T) {\n println!(\"summary : {}\", info.summarize() );\n}\nfn notify_msg (info: impl Summary + Display) {\n println!(\"summary : {}\", info.summarize() );\n}\nfn notify_msg (info: T) \nwhere \n T: Summary + Display,\n{\n println!(\"summary : {}\", info.summarize() );\n println!(\"display implement info : {}\", info);\n}\n```\n### trait as return\n- impl Trait can only return the same type, if it returns a different type, even if the Trait is implemented, an error will be reported\n\n## references\n- [the rust programming language](https://doc.rust-lang.org/book/)\n- [mooc course](https://time.geekbang.org/course/intro/100060601?tab=catalog)\n- [bilibili tutorial](https://www.bilibili.com/video/BV1hp4y1k7SV?p=50&spm_id_from=pageDriver)\n- [jianshu notes](https://www.jianshu.com/p/30d917790298)","slug":"rust/rust-02-basics","published":1,"updated":"2023-05-01T09:07:13.124Z","comments":1,"layout":"post","photos":[],"link":"","_id":"clk1e4wpr000h6hsj2ag6e8t0","content":"
frequently used cmd
1 2 3 4 5
rustc [filename].rs cargo new [project_name] cargo build [--release] cargo run [--release] cargo check # check whether compile success, no executible output
isize, usize indicates that the type is determined by the architecture of the computer. For example, on a 32 bit target, this is 4 bytes and on a 64 bit target, this is 8 bytes.
\n
0x: hex,0o Octal,0b binary,starting with b: byte (u8 only)
\n
\n
\n\n
\n
Number Literals
\n
Example
\n
\n\n
\n
Decimal
\n
98_222
\n
\n
\n
Hex
\n
0xff
\n
\n
\n
Octal
\n
0o77
\n
\n
\n
Binary
\n
0b1111_0000
\n
\n
\n
Byte(u8 only)
\n
b’A’
\n
\n
\n
Tuple
\n
The length of Tuple is fixed, and the length cannot be changed once declared
1 2 3 4 5 6 7 8 9 10
fnmain() { // tuple could be declared as mut letmut tuple_1 = ("Hello", 39, "Years"); lettuple_2:(i32, &str ) = (1983, "since."); tuple_1.0 = "Hi"; println!("{} {} {}", tuple_1.0, tuple_1.1, tuple_1.2); // destructure let (a,b) = tuple_2; println!("{} {}", a, b); }
\n
\n
array
\n
arrays in Rust have a fixed length.
\n
Vector is similar to an array, it is provided by the standard library, and its length can be changed
\n
\n
1 2 3 4 5 6 7 8 9 10 11
fnmain() {
letarr_test:[u8; 3] = [1,2,3]; println!("Number is {},{},{}", arr_test[0],arr_test[1],arr_test[2]);
letarr_test = ["I","love","you"]; println!("You said : {} {} {}", arr_test[0],arr_test[1],arr_test[2]);
letarr_test = [1;3]; println!("Call Num : {}&{}&{}", arr_test[0],arr_test[1],arr_test[2]); }
\n\n\n\n
String
\n
Basic data types are stored on the stack, but the String type is stored on the heap
1
lets = String::from("hello");
\n
push_str(): append a str slice a string
\n
push(): appends a single character to a String
1 2 3 4 5
fnmain() { letmut data = String::from("andy"); data.push_str(" is stronger"); data.push('!'); }
\n
+ operator, chaining strings. the left side of the + operator is the ownership of the string, and the right side is the string slice
\n
String is actually a wrapper for Vec, so the length can be measured by the len() method, but note that Len() is not length of character, but byte len
\n
String iteration
1 2 3 4 5 6 7 8 9 10 11 12 13
fnmain() { letmut data = String::from("andy"); data.push_str(" is stronger"); data.push('!');
foriin data.bytes() { /// }
foriin data.chars() { /// } }
\n
\n
Vector
\n
Vector is like any other struct. When Vector leaves the scope, the variable value is cleaned up, and all its elements are also cleaned up.
1 2 3 4 5 6 7
fnmain() { letvec: Vec<u16> = Vec::new(); letvec2: Vec<i32> = vec![3,4,5] // create vector by macro foriin vec2 { println!("Vector value is : {}", i); } }
\n
\n
HashMap
\n
HashMap is not preloaded, so it needs to be included use std::collections::HashMap
fnmain() { letcondition = 1; letx = if condition == 1 { "A" } else { "B" }; println!("Result x = {}" , x) ; }
\n
loop
1 2 3 4 5 6 7 8 9 10 11 12 13 14
fnmain() { letmut condition = 0;
letresult = 'outer: loop { // 'outer is label 'inner: loop { condition += 1; if3 == condition { break'outer3 * condition; // break outer loop } } }; println!("Loop result is : {}", result); /// Loop result is : 9 }
\n
rot
1 2 3 4 5 6
fnmain() { letarr = [3,2,3]; fornumin arr.iter() { println!("For value is {}", num); } }
\n
\n
Range iterator
\n
Range
1 2 3 4 5 6 7 8 9 10
fnmain() { fornumberin (1..=3) { println!("Number A is {}", number ); /// 1,2,3 } fornumberin (1..=3).rev() { /// rev means reverse, println!("Number B is {}", number ); /// 3,2,1 } }
\n
\n
struct
\n
If struct is declared mutable then all fields in the instance are mutable
You can define a function that does not take self as the first parameter in the impl block. This form is called an associated function, and the calling method is similar to String::from()
If do not want to deal with Err, can use unwarp() method. If result is Ok(val), return val. If Err, then call the panic! macro.
\n
expect can specify what the error message is, which is easier to debug
\n
\n
The question mark operator, ?
When writing code that calls many functions that return the Result type, the error handling can be tedious. The question mark operator, ?, hides some of the boilerplate of propagating errors up the call stack.
isize, usize indicates that the type is determined by the architecture of the computer. For example, on a 32 bit target, this is 4 bytes and on a 64 bit target, this is 8 bytes.
\n
0x: hex,0o Octal,0b binary,starting with b: byte (u8 only)
\n
\n
\n\n
\n
Number Literals
\n
Example
\n
\n\n
\n
Decimal
\n
98_222
\n
\n
\n
Hex
\n
0xff
\n
\n
\n
Octal
\n
0o77
\n
\n
\n
Binary
\n
0b1111_0000
\n
\n
\n
Byte(u8 only)
\n
b’A’
\n
\n
\n
Tuple
\n
The length of Tuple is fixed, and the length cannot be changed once declared
1 2 3 4 5 6 7 8 9 10
fnmain() { // tuple could be declared as mut letmut tuple_1 = ("Hello", 39, "Years"); lettuple_2:(i32, &str ) = (1983, "since."); tuple_1.0 = "Hi"; println!("{} {} {}", tuple_1.0, tuple_1.1, tuple_1.2); // destructure let (a,b) = tuple_2; println!("{} {}", a, b); }
\n
\n
array
\n
arrays in Rust have a fixed length.
\n
Vector is similar to an array, it is provided by the standard library, and its length can be changed
\n
\n
1 2 3 4 5 6 7 8 9 10 11
fnmain() {
letarr_test:[u8; 3] = [1,2,3]; println!("Number is {},{},{}", arr_test[0],arr_test[1],arr_test[2]);
letarr_test = ["I","love","you"]; println!("You said : {} {} {}", arr_test[0],arr_test[1],arr_test[2]);
letarr_test = [1;3]; println!("Call Num : {}&{}&{}", arr_test[0],arr_test[1],arr_test[2]); }
\n\n\n\n
String
\n
Basic data types are stored on the stack, but the String type is stored on the heap
1
lets = String::from("hello");
\n
push_str(): append a str slice a string
\n
push(): appends a single character to a String
1 2 3 4 5
fnmain() { letmut data = String::from("andy"); data.push_str(" is stronger"); data.push('!'); }
\n
+ operator, chaining strings. the left side of the + operator is the ownership of the string, and the right side is the string slice
\n
String is actually a wrapper for Vec, so the length can be measured by the len() method, but note that Len() is not length of character, but byte len
\n
String iteration
1 2 3 4 5 6 7 8 9 10 11 12 13
fnmain() { letmut data = String::from("andy"); data.push_str(" is stronger"); data.push('!');
foriin data.bytes() { /// }
foriin data.chars() { /// } }
\n
\n
Vector
\n
Vector is like any other struct. When Vector leaves the scope, the variable value is cleaned up, and all its elements are also cleaned up.
1 2 3 4 5 6 7
fnmain() { letvec: Vec<u16> = Vec::new(); letvec2: Vec<i32> = vec![3,4,5] // create vector by macro foriin vec2 { println!("Vector value is : {}", i); } }
\n
\n
HashMap
\n
HashMap is not preloaded, so it needs to be included use std::collections::HashMap
fnmain() { letcondition = 1; letx = if condition == 1 { "A" } else { "B" }; println!("Result x = {}" , x) ; }
\n
loop
1 2 3 4 5 6 7 8 9 10 11 12 13 14
fnmain() { letmut condition = 0;
letresult = 'outer: loop { // 'outer is label 'inner: loop { condition += 1; if3 == condition { break'outer3 * condition; // break outer loop } } }; println!("Loop result is : {}", result); /// Loop result is : 9 }
\n
rot
1 2 3 4 5 6
fnmain() { letarr = [3,2,3]; fornumin arr.iter() { println!("For value is {}", num); } }
\n
\n
Range iterator
\n
Range
1 2 3 4 5 6 7 8 9 10
fnmain() { fornumberin (1..=3) { println!("Number A is {}", number ); /// 1,2,3 } fornumberin (1..=3).rev() { /// rev means reverse, println!("Number B is {}", number ); /// 3,2,1 } }
\n
\n
struct
\n
If struct is declared mutable then all fields in the instance are mutable
You can define a function that does not take self as the first parameter in the impl block. This form is called an associated function, and the calling method is similar to String::from()
If do not want to deal with Err, can use unwarp() method. If result is Ok(val), return val. If Err, then call the panic! macro.
\n
expect can specify what the error message is, which is easier to debug
\n
\n
The question mark operator, ?
When writing code that calls many functions that return the Result type, the error handling can be tedious. The question mark operator, ?, hides some of the boilerplate of propagating errors up the call stack.
\n"},{"title":"rust smart pointer","date":"2022-10-30T03:00:38.000Z","_content":"\n## Overview\nThe most common kind of pointer in Rust is a reference (borrow but not own)\nSmart pointers, on the other hand, are data structures that not only act like a pointer but also have additional metadata and capabilities.\nreferences are pointers that only borrow data; in contrast, in many cases, smart pointers own the data they point to.\n\n### smart pointers example\n- String\n- Vec\nBoth these types count as smart pointers because they own some memory and allow you to manipulate it. They also have metadata (such as their capacity) and extra capabilities or guarantees (such as with String ensuring its data will always be valid UTF-8).\n\n### Deref & Drop\nSmart pointers are usually implemented using structs. The characteristic that distinguishes a smart pointer from an ordinary struct is that smart pointers implement the `Deref` and `Drop` traits.\n- The Deref trait allows an instance of the smart pointer struct to behave like a reference so you can write code that works with either references or smart pointers. \n- The Drop trait allows you to customize the code that is run when an instance of the smart pointer goes out of scope.\n\n### the most common smart pointers in the standard library:\n- `Box` for allocating values on the heap\n- `Rc`, a reference counting type that enables multiple ownership\n- `Ref` and `RefMut`, accessed through `RefCell`, a type that enforces the borrowing rules at runtime instead of compile time\n\n## Box\n### when to use\n- When you have a type whose size can’t be known at compile time and you want to use a value of that type in a context that requires an exact size. (such as cons)\n- When you have a large amount of data and you want to transfer ownership but ensure the data won’t be copied when you do so\n- When you want to own a value and you care only that it’s a type that implements a particular trait rather than being of a specific type\n\n\n### enabling recursive types with Box\nAt compile time, Rust needs to know how much space a type takes up\nOne type whose size can’t be known at compile time is a recursive type (cons list), use Box, which only contains a memory address\n\n```rust\nenum List {\n Cons(i32, List),\n Nil,\n}\n\nuse crate::List::{Cons, Nil};\nfn main() {\n let list = Cons(1, Cons(2, Cons(3, Nil))); // not allowed, infinite size\n}\n```\n\nuse Box\n```rust\nenum List {\n Cons(i32, Box),\n Nil,\n}\n\nuse crate::List::{Cons, Nil};\n\nfn main() {\n let list = Cons(1, Box::new(Cons(2, Box::new(Cons(3, Box::new(Nil))))));\n}\n```\n\n## Treating Smart Pointers Like Regular References with the Deref Trait\nImplementing the Deref trait allows you to customize the behavior of the dereference operator, `*`\nBy implementing Deref in such a way that a smart pointer can be treated like a regular reference, you can write code that operates on references and use that code with smart pointers too.\n\n### Defining Our Own Smart Pointer\n```rust\nuse std::ops::Deref;\n\nstruct MyBox(T); // The MyBox type is a tuple struct with one element of type T\n\nimpl MyBox {\n fn new(x: T) -> MyBox {\n MyBox(x)\n }\n}\n\nimpl Deref for MyBox {\n type Target = T;\n\n fn deref(&self) -> &Self::Target {\n &self.0\n }\n}\n\nfn main() {\n let x = 5;\n let y = MyBox::new(x);\n\n assert_eq!(5, x);\n assert_eq!(5, *y);\n}\n```\n- We fill in the body of the deref method with &self.0 so deref returns a reference to the value we want to access with the * operator. \n- behind the scenes Rust actually ran this code: *(y.deref()). Rust substitutes the * operator with a call to the deref method\n- The reason the deref method returns a reference to a value, and that the plain dereference outside the parentheses in *(y.deref()) is still necessary, is the ownership system. If the deref method returned the value directly instead of a reference to the value, the value would be moved out of self. We don’t want to take ownership of the inner value inside MyBox in this case or in most cases where we use the dereference operator.\n\n### Implicit Deref Coercions with Functions and Methods\nDeref coercion is a convenience that Rust performs on arguments to functions and methods. \nDeref coercion works only on types that implement the Deref trait. Deref coercion converts a reference to such a type into a reference to another type. For example, deref coercion can convert &String to &str because String implements the Deref trait such that it returns &str\nA sequence of calls to the deref method converts the type we provided into the type the parameter needs.\n\n```rust\nfn hello(name: &str) {\n println!(\"Hello, {}!\", name);\n}\n\nfn main() {\n let m = MyBox::new(String::from(\"Rust\"));\n hello(\"rust\"); // ok\n hello(&m); // also ok\n hello(&(*m)[..]); // without deref coercion. The (*m) dereferences the MyBox into a String. Then the & and [..] take a string slice of the String that is equal to the whole string to match the signature of hello\n}\n```\nHere we’re calling the hello function with the argument &m, which is a reference to a MyBox value. Because we implemented the Deref trait on MyBox, Rust can turn &MyBox into &String by calling deref. The standard library provides an implementation of Deref on String that returns a string slice. Rust calls deref again to turn the &String into &str, which matches the hello function’s definition.\n\n### How Deref Coercion Interacts with Mutability\nSimilar to how you use the Deref trait to override the * operator on immutable references, you can use the DerefMut trait to override the * operator on mutable references.\n\nRust does deref coercion when it finds types and trait implementations in three cases:\n- From &T to &U when T: Deref\n- From &mut T to &mut U when T: DerefMut\n- From &mut T to &U when T: Deref\n\n## Running Code on Cleanup with the Drop Trait\nDrop, which lets you customize what happens when a value is about to go out of scope. \n\n```rust\nstruct CustomSmartPointer {\n data: String,\n}\n\nimpl Drop for CustomSmartPointer {\n fn drop(&mut self) {\n println!(\"Dropping CustomSmartPointer with data `{}`!\", self.data);\n }\n}\n\nfn main() {\n let c = CustomSmartPointer {\n data: String::from(\"my stuff\"),\n };\n c.drop(); // not allowed\n let d = CustomSmartPointer {\n data: String::from(\"other stuff\"),\n };\n println!(\"CustomSmartPointers created.\");\n}\n\n```\n### Dropping a Value Early with std::mem::drop\nstd::mem::drop is in prelude, can use directly\n```rust\nstruct CustomSmartPointer {\n data: String,\n}\n\nimpl Drop for CustomSmartPointer {\n fn drop(&mut self) {\n println!(\"Dropping CustomSmartPointer with data `{}`!\", self.data);\n }\n}\n\nfn main() {\n let c = CustomSmartPointer {\n data: String::from(\"some data\"),\n };\n println!(\"CustomSmartPointer created.\");\n drop(c); // ok\n println!(\"CustomSmartPointer dropped before the end of main.\");\n} // c goes out of scope, will occur double drop\n\n```\n\n\n## Rc: the Reference Counted Smart Pointer\nIn the majority of cases, ownership is clear: you know exactly which variable owns a given value. However, there are cases when a single value might have multiple owners. \ntype keeps track of the number of references to a value to determine whether or not the value is still in use. If there are zero references to a value, the value can be cleaned up without any references becoming invalid.\n\nWe use the `Rc` type when we want to allocate some data on the heap for multiple parts of our program to read and we can’t determine at compile time which part will finish using the data last.\n\nRc is only for use in single-threaded scenarios\n\n### using Rc to share data\n\n![rc](/images/rust/pointers/rc.png)\nimplement use box will not work, as below\n```rust\nenum List {\n Cons(i32, Box),\n Nil,\n}\n\nuse crate::List::{Cons, Nil};\n\nfn main() {\n let a = Cons(5, Box::new(Cons(10, Box::new(Nil))));\n let b = Cons(3, Box::new(a)); // value moved here\n let c = Cons(4, Box::new(a)); // value used here after move\n}\n```\nuse Rc\n```rust\nenum List {\n Cons(i32, Rc),\n Nil,\n}\n\nuse crate::List::{Cons, Nil};\nuse std::rc::Rc;\n\nfn main() {\n let a = Rc::new(Cons(5, Rc::new(Cons(10, Rc::new(Nil)))));\n let b = Cons(3, Rc::clone(&a)); // shalow copy only reference, not data\n let c = Cons(4, Rc::clone(&a));\n}\n```\n\n\nWe could have called a.clone() rather than Rc::clone(&a), but Rust’s convention is to use Rc::clone in this case. The implementation of Rc::clone doesn’t make a deep copy of all the data like most types’ implementations of clone do. The call to Rc::clone only increments the reference count, which doesn’t take much time.\n\n### Cloning an Rc Increases the Reference Count\n```rust\nenum List {\n Cons(i32, Rc),\n Nil,\n}\n\nuse crate::List::{Cons, Nil};\nuse std::rc::Rc;\n\nfn main() {\n let a = Rc::new(Cons(5, Rc::new(Cons(10, Rc::new(Nil)))));\n println!(\"count after creating a = {}\", Rc::strong_count(&a)); // 1\n let b = Cons(3, Rc::clone(&a));\n println!(\"count after creating b = {}\", Rc::strong_count(&a)); // 2\n {\n let c = Cons(4, Rc::clone(&a));\n println!(\"count after creating c = {}\", Rc::strong_count(&a)); // 3\n }\n println!(\"count after c goes out of scope = {}\", Rc::strong_count(&a)); // 2\n}\n```\nWhat we can’t see in this example is that when b and then a go out of scope at the end of main, the count is then 0, and the Rc is cleaned up completely at that point.\n\n## RefCell and interior mutability pattern\nInterior mutability is a design pattern in Rust that allows you to mutate data even when there are immutable references to that data; normally, this action is disallowed by the borrowing rules.\nTo mutate data, the pattern uses unsafe code inside a data structure to bend Rust’s usual rules that govern mutation and borrowing.\nWe can use types that use the interior mutability pattern when we can ensure that the borrowing rules will be followed at runtime, even though the compiler can’t guarantee that. \nThe unsafe code involved is then wrapped in a safe API, and the outer type is still immutable.\n\n### Enforcing Borrowing Rules at Runtime with RefCell\nUnlike Rc, the RefCell type represents single ownership over the data it holds.\n\nrecall borrowing rules\n- At any given time, you can have either (but not both of) one mutable reference or any number of immutable references.\n- References must always be valid.\nWith references and Box, the borrowing rules’ invariants are enforced at compile time. With RefCell, these invariants are enforced at runtime. \nBecause RefCell allows mutable borrows checked at runtime, you can mutate the value inside the RefCell even when the RefCell is immutable.\n\n### Interior Mutability: A Mutable Borrow to an Immutable Value\n```rust\nfn main() {\n let x = 5;\n let y = &mut x; // not allowed. cannot borrow `x` as mutable, as it is not declared as mutable\n}\n```\n\n### A Use Case for Interior Mutability: Mock Objects\n```rust\npub trait Messenger {\n fn send(&self, msg: &str);\n}\n\npub struct LimitTracker<'a, T: Messenger> {\n messenger: &'a T,\n value: usize,\n max: usize,\n}\n\nimpl<'a, T> LimitTracker<'a, T>\nwhere\n T: Messenger,\n{\n pub fn new(messenger: &T, max: usize) -> LimitTracker {\n LimitTracker {\n messenger,\n value: 0,\n max,\n }\n }\n\n pub fn set_value(&mut self, value: usize) {\n self.value = value;\n\n let percentage_of_max = self.value as f64 / self.max as f64;\n\n if percentage_of_max >= 1.0 {\n self.messenger.send(\"Error: You are over your quota!\");\n } else if percentage_of_max >= 0.9 {\n self.messenger\n .send(\"Urgent warning: You've used up over 90% of your quota!\");\n } else if percentage_of_max >= 0.75 {\n self.messenger\n .send(\"Warning: You've used up over 75% of your quota!\");\n }\n }\n}\n\n```\na problematic usage\n```rust\npub trait Messenger {\n fn send(&self, msg: &str);\n}\n\npub struct LimitTracker<'a, T: Messenger> {\n messenger: &'a T,\n value: usize,\n max: usize,\n}\n\nimpl<'a, T> LimitTracker<'a, T>\nwhere\n T: Messenger,\n{\n pub fn new(messenger: &T, max: usize) -> LimitTracker {\n LimitTracker {\n messenger,\n value: 0,\n max,\n }\n }\n\n pub fn set_value(&mut self, value: usize) {\n self.value = value;\n\n let percentage_of_max = self.value as f64 / self.max as f64;\n\n if percentage_of_max >= 1.0 {\n self.messenger.send(\"Error: You are over your quota!\");\n } else if percentage_of_max >= 0.9 {\n self.messenger\n .send(\"Urgent warning: You've used up over 90% of your quota!\");\n } else if percentage_of_max >= 0.75 {\n self.messenger\n .send(\"Warning: You've used up over 75% of your quota!\");\n }\n }\n}\n\n#[cfg(test)]\nmod tests {\n use super::*;\n\n struct MockMessenger {\n sent_messages: Vec,\n }\n\n impl MockMessenger {\n fn new() -> MockMessenger {\n MockMessenger {\n sent_messages: vec![],\n }\n }\n }\n\n impl Messenger for MockMessenger {\n fn send(&self, message: &str) {\n self.sent_messages.push(String::from(message)); // not allowed. cannot borrow `self.sent_messages` as mutable, as it is behind a `&` reference\n }\n }\n\n #[test]\n fn it_sends_an_over_75_percent_warning_message() {\n let mock_messenger = MockMessenger::new();\n let mut limit_tracker = LimitTracker::new(&mock_messenger, 100);\n\n limit_tracker.set_value(80);\n\n assert_eq!(mock_messenger.sent_messages.len(), 1);\n }\n}\n\n```\nWe can’t modify the MockMessenger to keep track of the messages, because the send method takes an immutable reference to self. We also can’t take the suggestion from the error text to use &mut self instead, because then the signature of send wouldn’t match the signature in the Messenger trait definition\n\nThis is a situation in which interior mutability can help! \n```rust\npub trait Messenger {\n fn send(&self, msg: &str);\n}\n\npub struct LimitTracker<'a, T: Messenger> {\n messenger: &'a T,\n value: usize,\n max: usize,\n}\n\nimpl<'a, T> LimitTracker<'a, T>\nwhere\n T: Messenger,\n{\n pub fn new(messenger: &T, max: usize) -> LimitTracker {\n LimitTracker {\n messenger,\n value: 0,\n max,\n }\n }\n\n pub fn set_value(&mut self, value: usize) {\n self.value = value;\n\n let percentage_of_max = self.value as f64 / self.max as f64;\n\n if percentage_of_max >= 1.0 {\n self.messenger.send(\"Error: You are over your quota!\");\n } else if percentage_of_max >= 0.9 {\n self.messenger\n .send(\"Urgent warning: You've used up over 90% of your quota!\");\n } else if percentage_of_max >= 0.75 {\n self.messenger\n .send(\"Warning: You've used up over 75% of your quota!\");\n }\n }\n}\n\n#[cfg(test)]\nmod tests {\n use super::*;\n use std::cell::RefCell;\n\n struct MockMessenger {\n sent_messages: RefCell>,\n }\n\n impl MockMessenger {\n fn new() -> MockMessenger {\n MockMessenger {\n sent_messages: RefCell::new(vec![]),\n }\n }\n }\n\n impl Messenger for MockMessenger {\n fn send(&self, message: &str) {\n self.sent_messages.borrow_mut().push(String::from(message)); // call borrow_mut on the RefCell> in self.sent_messages to get a mutable reference to the value inside the RefCell>\n }\n }\n\n #[test]\n fn it_sends_an_over_75_percent_warning_message() {\n // --snip--\n let mock_messenger = MockMessenger::new();\n let mut limit_tracker = LimitTracker::new(&mock_messenger, 100);\n\n limit_tracker.set_value(80);\n\n assert_eq!(mock_messenger.sent_messages.borrow().len(), 1); // call borrow on the RefCell> to get an immutable reference to the vector.\n }\n}\n```\n\n### Keeping Track of Borrows at Runtime with RefCell\nWhen creating immutable and mutable references, we use the & and &mut syntax, respectively. With RefCell, we use the borrow and borrow_mut methods, which are part of the safe API that belongs to RefCell. **The borrow method returns the smart pointer type Ref, and borrow_mut returns the smart pointer type RefMut**. Both types implement Deref, so we can treat them like regular references.\n\nThe RefCell keeps track of how many Ref and RefMut smart pointers are currently active.RefCell lets us have many immutable borrows or one mutable borrow at any point in time. If we try to violate these rules, rather than getting a compiler error as we would with references, the implementation of RefCell will panic at runtime. \n```rust\nimpl Messenger for MockMessenger {\n fn send(&self, message: &str) {\n let mut one_borrow = self.sent_messages.borrow_mut();\n let mut two_borrow = self.sent_messages.borrow_mut();\n\n one_borrow.push(String::from(message));\n two_borrow.push(String::from(message));\n }\n }\n```\nWhen we run the tests for our library, the code in will compile without any errors, but the test will fail\nthread 'main' panicked at 'already borrowed\n\n### Having Multiple Owners of Mutable Data by Combining Rc and RefCell\nA common way to use RefCell is in combination with Rc. If you have an Rc that holds a RefCell, you can get a value that can have multiple owners and that you can mutate!\n```rust\n#[derive(Debug)]\nenum List {\n Cons(Rc>, Rc),\n Nil,\n}\n\nuse crate::List::{Cons, Nil};\nuse std::cell::RefCell;\nuse std::rc::Rc;\n\nfn main() {\n let value = Rc::new(RefCell::new(5)); // We create a value that is an instance of Rc> and store it in a variable named value so we can access it directly later.\n\n let a = Rc::new(Cons(Rc::clone(&value), Rc::new(Nil))); // Then we create a List in a with a Cons variant that holds value. We need to clone value so both a and value have ownership of the inner 5 value rather than transferring ownership from value to a or having a borrow from value. We wrap the list a in an Rc so when we create lists b and c, they can both refer to a\n\n let b = Cons(Rc::new(RefCell::new(3)), Rc::clone(&a));\n let c = Cons(Rc::new(RefCell::new(4)), Rc::clone(&a));\n\n *value.borrow_mut() += 10; // After we’ve created the lists in a, b, and c, we add 10 to the value in value. We do this by calling borrow_mut on value, which uses the automatic dereferencing feature to dereference the Rc to the inner RefCell value. The borrow_mut method returns a RefMut smart pointer, and we use the dereference operator on it and change the inner value.\n\n println!(\"a after = {:?}\", a);\n println!(\"b after = {:?}\", b);\n println!(\"c after = {:?}\", c);\n}\n```\n\n**The standard library has other types that provide interior mutability, such as Cell, which is similar except that instead of giving references to the inner value, the value is copied in and out of the Cell. There’s also Mutex, which offers interior mutability that’s safe to use across threads;** \n\n## Reference Cycles Can Leak Memory\nRust’s memory safety guarantees make it difficult, but not impossible, to accidentally create memory that is never cleaned up (known as a memory leak).\n\n### Creating a Reference Cycle\n```rust\nuse crate::List::{Cons, Nil};\nuse std::cell::RefCell;\nuse std::rc::Rc;\n\n#[derive(Debug)]\nenum List {\n Cons(i32, RefCell>), // The second element in the Cons variant is now RefCell>, meaning that we want to modify which List value a Cons variant is pointing to. \n Nil,\n}\n\nimpl List {\n fn tail(&self) -> Option<&RefCell>> { // We’re also adding a tail method to make it convenient for us to access the second item if we have a Cons variant.\n match self {\n Cons(_, item) => Some(item),\n Nil => None,\n }\n }\n}\n\nfn main() {\n use crate::List::{Cons, Nil};\nuse std::cell::RefCell;\nuse std::rc::Rc;\n\n#[derive(Debug)]\nenum List {\n Cons(i32, RefCell>),\n Nil,\n}\n\nimpl List {\n fn tail(&self) -> Option<&RefCell>> {\n match self {\n Cons(_, item) => Some(item),\n Nil => None,\n }\n }\n}\n\nfn main() {\n let a = Rc::new(Cons(5, RefCell::new(Rc::new(Nil))));\n\n println!(\"a initial rc count = {}\", Rc::strong_count(&a));\n println!(\"a next item = {:?}\", a.tail());\n\n let b = Rc::new(Cons(10, RefCell::new(Rc::clone(&a)))); // his code creates a list in a and a list in b that points to the list in a\n\n println!(\"a rc count after b creation = {}\", Rc::strong_count(&a));\n println!(\"b initial rc count = {}\", Rc::strong_count(&b));\n println!(\"b next item = {:?}\", b.tail());\n\n if let Some(link) = a.tail() {\n *link.borrow_mut() = Rc::clone(&b); // modifies the list in a to point to b, creating a reference cycle\n }\n\n println!(\"b rc count after changing a = {}\", Rc::strong_count(&b));\n println!(\"a rc count after changing a = {}\", Rc::strong_count(&a));\n\n // Uncomment the next line to see that we have a cycle;\n // it will overflow the stack\n // println!(\"a next item = {:?}\", a.tail());\n} // At the end of main, Rust drops the variable b, which decreases the reference count of the Rc instance from 2 to 1. The memory that Rc has on the heap won’t be dropped at this point, because its reference count is 1, not 0. Then Rust drops a, which decreases the reference count of the a Rc instance from 2 to 1 as well. This instance’s memory can’t be dropped either, because the other Rc instance still refers to it. The memory allocated to the list will remain uncollected forever.\n```\n![cycle-ref](/images/rust/pointers/cycle.ref.png)\n\n### Preventing Reference Cycles: Turning an Rc into a Weak\nSo far, we’ve demonstrated that calling Rc::clone increases the strong_count of an Rc instance, and an Rc instance is only cleaned up if its strong_count is 0. You can also create a weak reference to the value within an Rc instance by calling Rc::downgrade and passing a reference to the Rc. When you call Rc::downgrade, you get a smart pointer of type Weak. Instead of increasing the strong_count in the Rc instance by 1, calling Rc::downgrade increases the weak_count by 1. The Rc type uses weak_count to keep track of how many Weak references exist, similar to strong_count. The difference is the weak_count doesn’t need to be 0 for the Rc instance to be cleaned up.\n\nStrong references are how you can share ownership of an Rc instance. Weak references don’t express an ownership relationship. They won’t cause a reference cycle because any cycle involving some weak references will be broken once the strong reference count of values involved is 0.\n\nBecause the value that Weak references might have been dropped, to do anything with the value that a Weak is pointing to, you must make sure the value still exists. Do this by calling the upgrade method on a Weak instance, which will return an Option>. You’ll get a result of Some if the Rc value has not been dropped yet and a result of None if the Rc value has been dropped. \n\n\n### Creating a Tree Data Structure: a Node with Child Nodes\n```rust\nuse std::cell::RefCell;\nuse std::rc::Rc;\n\n#[derive(Debug)]\nstruct Node {\n value: i32,\n parent: RefCell>, // To make the child node aware of its parent, we need to add a parent field to our Node struct definition. The trouble is in deciding what the type of parent should be. We know it can’t contain an Rc, because that would create a reference cycle with leaf.parent pointing to branch and branch.children pointing to leaf, which would cause their strong_count values to never be 0.\n children: RefCell>>,\n}\n\nfn main() {\n\n let leaf = Rc::new(Node {\n value: 3,\n parent: RefCell::new(Weak::new()),\n children: RefCell::new(vec![]),\n });\n\n println!(\"leaf parent = {:?}\", leaf.parent.borrow().upgrade()); // try to get a reference to the parent of leaf by using the upgrade method, we get a None value. \n\n let branch = Rc::new(Node {\n value: 5,\n parent: RefCell::new(Weak::new()),\n children: RefCell::new(vec![Rc::clone(&leaf)]), // We clone the Rc in leaf and store that in branch, meaning the Node in leaf now has two owners: leaf and branch. \n });\n\n *leaf.parent.borrow_mut() = Rc::downgrade(&branch); // use the Rc::downgrade function to create a Weak reference to branch from the Rc in branch.\n\n println!(\"leaf parent = {:?}\", leaf.parent.borrow().upgrade());\n\n \n}\n```\n\n### Visualizing Changes to strong_count and weak_count\n```rust\nuse std::cell::RefCell;\nuse std::rc::{Rc, Weak};\n\n#[derive(Debug)]\nstruct Node {\n value: i32,\n parent: RefCell>,\n children: RefCell>>,\n}\n\nfn main() {\n let leaf = Rc::new(Node {\n value: 3,\n parent: RefCell::new(Weak::new()),\n children: RefCell::new(vec![]),\n });\n\n println!(\n \"leaf strong = {}, weak = {}\",\n Rc::strong_count(&leaf),\n Rc::weak_count(&leaf),\n );\n\n {\n let branch = Rc::new(Node {\n value: 5,\n parent: RefCell::new(Weak::new()),\n children: RefCell::new(vec![Rc::clone(&leaf)]),\n });\n\n *leaf.parent.borrow_mut() = Rc::downgrade(&branch);\n\n println!(\n \"branch strong = {}, weak = {}\",\n Rc::strong_count(&branch),\n Rc::weak_count(&branch),\n );\n\n println!(\n \"leaf strong = {}, weak = {}\",\n Rc::strong_count(&leaf),\n Rc::weak_count(&leaf),\n );\n }\n\n println!(\"leaf parent = {:?}\", leaf.parent.borrow().upgrade());\n println!(\n \"leaf strong = {}, weak = {}\",\n Rc::strong_count(&leaf),\n Rc::weak_count(&leaf),\n );\n}\n```","source":"_posts/rust/rust-06-smart-pointer.md","raw":"---\ntitle: rust smart pointer\ndate: 2022-10-30 11:00:38\ntags: [rust]\n---\n\n## Overview\nThe most common kind of pointer in Rust is a reference (borrow but not own)\nSmart pointers, on the other hand, are data structures that not only act like a pointer but also have additional metadata and capabilities.\nreferences are pointers that only borrow data; in contrast, in many cases, smart pointers own the data they point to.\n\n### smart pointers example\n- String\n- Vec\nBoth these types count as smart pointers because they own some memory and allow you to manipulate it. They also have metadata (such as their capacity) and extra capabilities or guarantees (such as with String ensuring its data will always be valid UTF-8).\n\n### Deref & Drop\nSmart pointers are usually implemented using structs. The characteristic that distinguishes a smart pointer from an ordinary struct is that smart pointers implement the `Deref` and `Drop` traits.\n- The Deref trait allows an instance of the smart pointer struct to behave like a reference so you can write code that works with either references or smart pointers. \n- The Drop trait allows you to customize the code that is run when an instance of the smart pointer goes out of scope.\n\n### the most common smart pointers in the standard library:\n- `Box` for allocating values on the heap\n- `Rc`, a reference counting type that enables multiple ownership\n- `Ref` and `RefMut`, accessed through `RefCell`, a type that enforces the borrowing rules at runtime instead of compile time\n\n## Box\n### when to use\n- When you have a type whose size can’t be known at compile time and you want to use a value of that type in a context that requires an exact size. (such as cons)\n- When you have a large amount of data and you want to transfer ownership but ensure the data won’t be copied when you do so\n- When you want to own a value and you care only that it’s a type that implements a particular trait rather than being of a specific type\n\n\n### enabling recursive types with Box\nAt compile time, Rust needs to know how much space a type takes up\nOne type whose size can’t be known at compile time is a recursive type (cons list), use Box, which only contains a memory address\n\n```rust\nenum List {\n Cons(i32, List),\n Nil,\n}\n\nuse crate::List::{Cons, Nil};\nfn main() {\n let list = Cons(1, Cons(2, Cons(3, Nil))); // not allowed, infinite size\n}\n```\n\nuse Box\n```rust\nenum List {\n Cons(i32, Box),\n Nil,\n}\n\nuse crate::List::{Cons, Nil};\n\nfn main() {\n let list = Cons(1, Box::new(Cons(2, Box::new(Cons(3, Box::new(Nil))))));\n}\n```\n\n## Treating Smart Pointers Like Regular References with the Deref Trait\nImplementing the Deref trait allows you to customize the behavior of the dereference operator, `*`\nBy implementing Deref in such a way that a smart pointer can be treated like a regular reference, you can write code that operates on references and use that code with smart pointers too.\n\n### Defining Our Own Smart Pointer\n```rust\nuse std::ops::Deref;\n\nstruct MyBox(T); // The MyBox type is a tuple struct with one element of type T\n\nimpl MyBox {\n fn new(x: T) -> MyBox {\n MyBox(x)\n }\n}\n\nimpl Deref for MyBox {\n type Target = T;\n\n fn deref(&self) -> &Self::Target {\n &self.0\n }\n}\n\nfn main() {\n let x = 5;\n let y = MyBox::new(x);\n\n assert_eq!(5, x);\n assert_eq!(5, *y);\n}\n```\n- We fill in the body of the deref method with &self.0 so deref returns a reference to the value we want to access with the * operator. \n- behind the scenes Rust actually ran this code: *(y.deref()). Rust substitutes the * operator with a call to the deref method\n- The reason the deref method returns a reference to a value, and that the plain dereference outside the parentheses in *(y.deref()) is still necessary, is the ownership system. If the deref method returned the value directly instead of a reference to the value, the value would be moved out of self. We don’t want to take ownership of the inner value inside MyBox in this case or in most cases where we use the dereference operator.\n\n### Implicit Deref Coercions with Functions and Methods\nDeref coercion is a convenience that Rust performs on arguments to functions and methods. \nDeref coercion works only on types that implement the Deref trait. Deref coercion converts a reference to such a type into a reference to another type. For example, deref coercion can convert &String to &str because String implements the Deref trait such that it returns &str\nA sequence of calls to the deref method converts the type we provided into the type the parameter needs.\n\n```rust\nfn hello(name: &str) {\n println!(\"Hello, {}!\", name);\n}\n\nfn main() {\n let m = MyBox::new(String::from(\"Rust\"));\n hello(\"rust\"); // ok\n hello(&m); // also ok\n hello(&(*m)[..]); // without deref coercion. The (*m) dereferences the MyBox into a String. Then the & and [..] take a string slice of the String that is equal to the whole string to match the signature of hello\n}\n```\nHere we’re calling the hello function with the argument &m, which is a reference to a MyBox value. Because we implemented the Deref trait on MyBox, Rust can turn &MyBox into &String by calling deref. The standard library provides an implementation of Deref on String that returns a string slice. Rust calls deref again to turn the &String into &str, which matches the hello function’s definition.\n\n### How Deref Coercion Interacts with Mutability\nSimilar to how you use the Deref trait to override the * operator on immutable references, you can use the DerefMut trait to override the * operator on mutable references.\n\nRust does deref coercion when it finds types and trait implementations in three cases:\n- From &T to &U when T: Deref\n- From &mut T to &mut U when T: DerefMut\n- From &mut T to &U when T: Deref\n\n## Running Code on Cleanup with the Drop Trait\nDrop, which lets you customize what happens when a value is about to go out of scope. \n\n```rust\nstruct CustomSmartPointer {\n data: String,\n}\n\nimpl Drop for CustomSmartPointer {\n fn drop(&mut self) {\n println!(\"Dropping CustomSmartPointer with data `{}`!\", self.data);\n }\n}\n\nfn main() {\n let c = CustomSmartPointer {\n data: String::from(\"my stuff\"),\n };\n c.drop(); // not allowed\n let d = CustomSmartPointer {\n data: String::from(\"other stuff\"),\n };\n println!(\"CustomSmartPointers created.\");\n}\n\n```\n### Dropping a Value Early with std::mem::drop\nstd::mem::drop is in prelude, can use directly\n```rust\nstruct CustomSmartPointer {\n data: String,\n}\n\nimpl Drop for CustomSmartPointer {\n fn drop(&mut self) {\n println!(\"Dropping CustomSmartPointer with data `{}`!\", self.data);\n }\n}\n\nfn main() {\n let c = CustomSmartPointer {\n data: String::from(\"some data\"),\n };\n println!(\"CustomSmartPointer created.\");\n drop(c); // ok\n println!(\"CustomSmartPointer dropped before the end of main.\");\n} // c goes out of scope, will occur double drop\n\n```\n\n\n## Rc: the Reference Counted Smart Pointer\nIn the majority of cases, ownership is clear: you know exactly which variable owns a given value. However, there are cases when a single value might have multiple owners. \ntype keeps track of the number of references to a value to determine whether or not the value is still in use. If there are zero references to a value, the value can be cleaned up without any references becoming invalid.\n\nWe use the `Rc` type when we want to allocate some data on the heap for multiple parts of our program to read and we can’t determine at compile time which part will finish using the data last.\n\nRc is only for use in single-threaded scenarios\n\n### using Rc to share data\n\n![rc](/images/rust/pointers/rc.png)\nimplement use box will not work, as below\n```rust\nenum List {\n Cons(i32, Box),\n Nil,\n}\n\nuse crate::List::{Cons, Nil};\n\nfn main() {\n let a = Cons(5, Box::new(Cons(10, Box::new(Nil))));\n let b = Cons(3, Box::new(a)); // value moved here\n let c = Cons(4, Box::new(a)); // value used here after move\n}\n```\nuse Rc\n```rust\nenum List {\n Cons(i32, Rc),\n Nil,\n}\n\nuse crate::List::{Cons, Nil};\nuse std::rc::Rc;\n\nfn main() {\n let a = Rc::new(Cons(5, Rc::new(Cons(10, Rc::new(Nil)))));\n let b = Cons(3, Rc::clone(&a)); // shalow copy only reference, not data\n let c = Cons(4, Rc::clone(&a));\n}\n```\n\n\nWe could have called a.clone() rather than Rc::clone(&a), but Rust’s convention is to use Rc::clone in this case. The implementation of Rc::clone doesn’t make a deep copy of all the data like most types’ implementations of clone do. The call to Rc::clone only increments the reference count, which doesn’t take much time.\n\n### Cloning an Rc Increases the Reference Count\n```rust\nenum List {\n Cons(i32, Rc),\n Nil,\n}\n\nuse crate::List::{Cons, Nil};\nuse std::rc::Rc;\n\nfn main() {\n let a = Rc::new(Cons(5, Rc::new(Cons(10, Rc::new(Nil)))));\n println!(\"count after creating a = {}\", Rc::strong_count(&a)); // 1\n let b = Cons(3, Rc::clone(&a));\n println!(\"count after creating b = {}\", Rc::strong_count(&a)); // 2\n {\n let c = Cons(4, Rc::clone(&a));\n println!(\"count after creating c = {}\", Rc::strong_count(&a)); // 3\n }\n println!(\"count after c goes out of scope = {}\", Rc::strong_count(&a)); // 2\n}\n```\nWhat we can’t see in this example is that when b and then a go out of scope at the end of main, the count is then 0, and the Rc is cleaned up completely at that point.\n\n## RefCell and interior mutability pattern\nInterior mutability is a design pattern in Rust that allows you to mutate data even when there are immutable references to that data; normally, this action is disallowed by the borrowing rules.\nTo mutate data, the pattern uses unsafe code inside a data structure to bend Rust’s usual rules that govern mutation and borrowing.\nWe can use types that use the interior mutability pattern when we can ensure that the borrowing rules will be followed at runtime, even though the compiler can’t guarantee that. \nThe unsafe code involved is then wrapped in a safe API, and the outer type is still immutable.\n\n### Enforcing Borrowing Rules at Runtime with RefCell\nUnlike Rc, the RefCell type represents single ownership over the data it holds.\n\nrecall borrowing rules\n- At any given time, you can have either (but not both of) one mutable reference or any number of immutable references.\n- References must always be valid.\nWith references and Box, the borrowing rules’ invariants are enforced at compile time. With RefCell, these invariants are enforced at runtime. \nBecause RefCell allows mutable borrows checked at runtime, you can mutate the value inside the RefCell even when the RefCell is immutable.\n\n### Interior Mutability: A Mutable Borrow to an Immutable Value\n```rust\nfn main() {\n let x = 5;\n let y = &mut x; // not allowed. cannot borrow `x` as mutable, as it is not declared as mutable\n}\n```\n\n### A Use Case for Interior Mutability: Mock Objects\n```rust\npub trait Messenger {\n fn send(&self, msg: &str);\n}\n\npub struct LimitTracker<'a, T: Messenger> {\n messenger: &'a T,\n value: usize,\n max: usize,\n}\n\nimpl<'a, T> LimitTracker<'a, T>\nwhere\n T: Messenger,\n{\n pub fn new(messenger: &T, max: usize) -> LimitTracker {\n LimitTracker {\n messenger,\n value: 0,\n max,\n }\n }\n\n pub fn set_value(&mut self, value: usize) {\n self.value = value;\n\n let percentage_of_max = self.value as f64 / self.max as f64;\n\n if percentage_of_max >= 1.0 {\n self.messenger.send(\"Error: You are over your quota!\");\n } else if percentage_of_max >= 0.9 {\n self.messenger\n .send(\"Urgent warning: You've used up over 90% of your quota!\");\n } else if percentage_of_max >= 0.75 {\n self.messenger\n .send(\"Warning: You've used up over 75% of your quota!\");\n }\n }\n}\n\n```\na problematic usage\n```rust\npub trait Messenger {\n fn send(&self, msg: &str);\n}\n\npub struct LimitTracker<'a, T: Messenger> {\n messenger: &'a T,\n value: usize,\n max: usize,\n}\n\nimpl<'a, T> LimitTracker<'a, T>\nwhere\n T: Messenger,\n{\n pub fn new(messenger: &T, max: usize) -> LimitTracker {\n LimitTracker {\n messenger,\n value: 0,\n max,\n }\n }\n\n pub fn set_value(&mut self, value: usize) {\n self.value = value;\n\n let percentage_of_max = self.value as f64 / self.max as f64;\n\n if percentage_of_max >= 1.0 {\n self.messenger.send(\"Error: You are over your quota!\");\n } else if percentage_of_max >= 0.9 {\n self.messenger\n .send(\"Urgent warning: You've used up over 90% of your quota!\");\n } else if percentage_of_max >= 0.75 {\n self.messenger\n .send(\"Warning: You've used up over 75% of your quota!\");\n }\n }\n}\n\n#[cfg(test)]\nmod tests {\n use super::*;\n\n struct MockMessenger {\n sent_messages: Vec,\n }\n\n impl MockMessenger {\n fn new() -> MockMessenger {\n MockMessenger {\n sent_messages: vec![],\n }\n }\n }\n\n impl Messenger for MockMessenger {\n fn send(&self, message: &str) {\n self.sent_messages.push(String::from(message)); // not allowed. cannot borrow `self.sent_messages` as mutable, as it is behind a `&` reference\n }\n }\n\n #[test]\n fn it_sends_an_over_75_percent_warning_message() {\n let mock_messenger = MockMessenger::new();\n let mut limit_tracker = LimitTracker::new(&mock_messenger, 100);\n\n limit_tracker.set_value(80);\n\n assert_eq!(mock_messenger.sent_messages.len(), 1);\n }\n}\n\n```\nWe can’t modify the MockMessenger to keep track of the messages, because the send method takes an immutable reference to self. We also can’t take the suggestion from the error text to use &mut self instead, because then the signature of send wouldn’t match the signature in the Messenger trait definition\n\nThis is a situation in which interior mutability can help! \n```rust\npub trait Messenger {\n fn send(&self, msg: &str);\n}\n\npub struct LimitTracker<'a, T: Messenger> {\n messenger: &'a T,\n value: usize,\n max: usize,\n}\n\nimpl<'a, T> LimitTracker<'a, T>\nwhere\n T: Messenger,\n{\n pub fn new(messenger: &T, max: usize) -> LimitTracker {\n LimitTracker {\n messenger,\n value: 0,\n max,\n }\n }\n\n pub fn set_value(&mut self, value: usize) {\n self.value = value;\n\n let percentage_of_max = self.value as f64 / self.max as f64;\n\n if percentage_of_max >= 1.0 {\n self.messenger.send(\"Error: You are over your quota!\");\n } else if percentage_of_max >= 0.9 {\n self.messenger\n .send(\"Urgent warning: You've used up over 90% of your quota!\");\n } else if percentage_of_max >= 0.75 {\n self.messenger\n .send(\"Warning: You've used up over 75% of your quota!\");\n }\n }\n}\n\n#[cfg(test)]\nmod tests {\n use super::*;\n use std::cell::RefCell;\n\n struct MockMessenger {\n sent_messages: RefCell>,\n }\n\n impl MockMessenger {\n fn new() -> MockMessenger {\n MockMessenger {\n sent_messages: RefCell::new(vec![]),\n }\n }\n }\n\n impl Messenger for MockMessenger {\n fn send(&self, message: &str) {\n self.sent_messages.borrow_mut().push(String::from(message)); // call borrow_mut on the RefCell> in self.sent_messages to get a mutable reference to the value inside the RefCell>\n }\n }\n\n #[test]\n fn it_sends_an_over_75_percent_warning_message() {\n // --snip--\n let mock_messenger = MockMessenger::new();\n let mut limit_tracker = LimitTracker::new(&mock_messenger, 100);\n\n limit_tracker.set_value(80);\n\n assert_eq!(mock_messenger.sent_messages.borrow().len(), 1); // call borrow on the RefCell> to get an immutable reference to the vector.\n }\n}\n```\n\n### Keeping Track of Borrows at Runtime with RefCell\nWhen creating immutable and mutable references, we use the & and &mut syntax, respectively. With RefCell, we use the borrow and borrow_mut methods, which are part of the safe API that belongs to RefCell. **The borrow method returns the smart pointer type Ref, and borrow_mut returns the smart pointer type RefMut**. Both types implement Deref, so we can treat them like regular references.\n\nThe RefCell keeps track of how many Ref and RefMut smart pointers are currently active.RefCell lets us have many immutable borrows or one mutable borrow at any point in time. If we try to violate these rules, rather than getting a compiler error as we would with references, the implementation of RefCell will panic at runtime. \n```rust\nimpl Messenger for MockMessenger {\n fn send(&self, message: &str) {\n let mut one_borrow = self.sent_messages.borrow_mut();\n let mut two_borrow = self.sent_messages.borrow_mut();\n\n one_borrow.push(String::from(message));\n two_borrow.push(String::from(message));\n }\n }\n```\nWhen we run the tests for our library, the code in will compile without any errors, but the test will fail\nthread 'main' panicked at 'already borrowed\n\n### Having Multiple Owners of Mutable Data by Combining Rc and RefCell\nA common way to use RefCell is in combination with Rc. If you have an Rc that holds a RefCell, you can get a value that can have multiple owners and that you can mutate!\n```rust\n#[derive(Debug)]\nenum List {\n Cons(Rc>, Rc),\n Nil,\n}\n\nuse crate::List::{Cons, Nil};\nuse std::cell::RefCell;\nuse std::rc::Rc;\n\nfn main() {\n let value = Rc::new(RefCell::new(5)); // We create a value that is an instance of Rc> and store it in a variable named value so we can access it directly later.\n\n let a = Rc::new(Cons(Rc::clone(&value), Rc::new(Nil))); // Then we create a List in a with a Cons variant that holds value. We need to clone value so both a and value have ownership of the inner 5 value rather than transferring ownership from value to a or having a borrow from value. We wrap the list a in an Rc so when we create lists b and c, they can both refer to a\n\n let b = Cons(Rc::new(RefCell::new(3)), Rc::clone(&a));\n let c = Cons(Rc::new(RefCell::new(4)), Rc::clone(&a));\n\n *value.borrow_mut() += 10; // After we’ve created the lists in a, b, and c, we add 10 to the value in value. We do this by calling borrow_mut on value, which uses the automatic dereferencing feature to dereference the Rc to the inner RefCell value. The borrow_mut method returns a RefMut smart pointer, and we use the dereference operator on it and change the inner value.\n\n println!(\"a after = {:?}\", a);\n println!(\"b after = {:?}\", b);\n println!(\"c after = {:?}\", c);\n}\n```\n\n**The standard library has other types that provide interior mutability, such as Cell, which is similar except that instead of giving references to the inner value, the value is copied in and out of the Cell. There’s also Mutex, which offers interior mutability that’s safe to use across threads;** \n\n## Reference Cycles Can Leak Memory\nRust’s memory safety guarantees make it difficult, but not impossible, to accidentally create memory that is never cleaned up (known as a memory leak).\n\n### Creating a Reference Cycle\n```rust\nuse crate::List::{Cons, Nil};\nuse std::cell::RefCell;\nuse std::rc::Rc;\n\n#[derive(Debug)]\nenum List {\n Cons(i32, RefCell>), // The second element in the Cons variant is now RefCell>, meaning that we want to modify which List value a Cons variant is pointing to. \n Nil,\n}\n\nimpl List {\n fn tail(&self) -> Option<&RefCell>> { // We’re also adding a tail method to make it convenient for us to access the second item if we have a Cons variant.\n match self {\n Cons(_, item) => Some(item),\n Nil => None,\n }\n }\n}\n\nfn main() {\n use crate::List::{Cons, Nil};\nuse std::cell::RefCell;\nuse std::rc::Rc;\n\n#[derive(Debug)]\nenum List {\n Cons(i32, RefCell>),\n Nil,\n}\n\nimpl List {\n fn tail(&self) -> Option<&RefCell>> {\n match self {\n Cons(_, item) => Some(item),\n Nil => None,\n }\n }\n}\n\nfn main() {\n let a = Rc::new(Cons(5, RefCell::new(Rc::new(Nil))));\n\n println!(\"a initial rc count = {}\", Rc::strong_count(&a));\n println!(\"a next item = {:?}\", a.tail());\n\n let b = Rc::new(Cons(10, RefCell::new(Rc::clone(&a)))); // his code creates a list in a and a list in b that points to the list in a\n\n println!(\"a rc count after b creation = {}\", Rc::strong_count(&a));\n println!(\"b initial rc count = {}\", Rc::strong_count(&b));\n println!(\"b next item = {:?}\", b.tail());\n\n if let Some(link) = a.tail() {\n *link.borrow_mut() = Rc::clone(&b); // modifies the list in a to point to b, creating a reference cycle\n }\n\n println!(\"b rc count after changing a = {}\", Rc::strong_count(&b));\n println!(\"a rc count after changing a = {}\", Rc::strong_count(&a));\n\n // Uncomment the next line to see that we have a cycle;\n // it will overflow the stack\n // println!(\"a next item = {:?}\", a.tail());\n} // At the end of main, Rust drops the variable b, which decreases the reference count of the Rc instance from 2 to 1. The memory that Rc has on the heap won’t be dropped at this point, because its reference count is 1, not 0. Then Rust drops a, which decreases the reference count of the a Rc instance from 2 to 1 as well. This instance’s memory can’t be dropped either, because the other Rc instance still refers to it. The memory allocated to the list will remain uncollected forever.\n```\n![cycle-ref](/images/rust/pointers/cycle.ref.png)\n\n### Preventing Reference Cycles: Turning an Rc into a Weak\nSo far, we’ve demonstrated that calling Rc::clone increases the strong_count of an Rc instance, and an Rc instance is only cleaned up if its strong_count is 0. You can also create a weak reference to the value within an Rc instance by calling Rc::downgrade and passing a reference to the Rc. When you call Rc::downgrade, you get a smart pointer of type Weak. Instead of increasing the strong_count in the Rc instance by 1, calling Rc::downgrade increases the weak_count by 1. The Rc type uses weak_count to keep track of how many Weak references exist, similar to strong_count. The difference is the weak_count doesn’t need to be 0 for the Rc instance to be cleaned up.\n\nStrong references are how you can share ownership of an Rc instance. Weak references don’t express an ownership relationship. They won’t cause a reference cycle because any cycle involving some weak references will be broken once the strong reference count of values involved is 0.\n\nBecause the value that Weak references might have been dropped, to do anything with the value that a Weak is pointing to, you must make sure the value still exists. Do this by calling the upgrade method on a Weak instance, which will return an Option>. You’ll get a result of Some if the Rc value has not been dropped yet and a result of None if the Rc value has been dropped. \n\n\n### Creating a Tree Data Structure: a Node with Child Nodes\n```rust\nuse std::cell::RefCell;\nuse std::rc::Rc;\n\n#[derive(Debug)]\nstruct Node {\n value: i32,\n parent: RefCell>, // To make the child node aware of its parent, we need to add a parent field to our Node struct definition. The trouble is in deciding what the type of parent should be. We know it can’t contain an Rc, because that would create a reference cycle with leaf.parent pointing to branch and branch.children pointing to leaf, which would cause their strong_count values to never be 0.\n children: RefCell>>,\n}\n\nfn main() {\n\n let leaf = Rc::new(Node {\n value: 3,\n parent: RefCell::new(Weak::new()),\n children: RefCell::new(vec![]),\n });\n\n println!(\"leaf parent = {:?}\", leaf.parent.borrow().upgrade()); // try to get a reference to the parent of leaf by using the upgrade method, we get a None value. \n\n let branch = Rc::new(Node {\n value: 5,\n parent: RefCell::new(Weak::new()),\n children: RefCell::new(vec![Rc::clone(&leaf)]), // We clone the Rc in leaf and store that in branch, meaning the Node in leaf now has two owners: leaf and branch. \n });\n\n *leaf.parent.borrow_mut() = Rc::downgrade(&branch); // use the Rc::downgrade function to create a Weak reference to branch from the Rc in branch.\n\n println!(\"leaf parent = {:?}\", leaf.parent.borrow().upgrade());\n\n \n}\n```\n\n### Visualizing Changes to strong_count and weak_count\n```rust\nuse std::cell::RefCell;\nuse std::rc::{Rc, Weak};\n\n#[derive(Debug)]\nstruct Node {\n value: i32,\n parent: RefCell>,\n children: RefCell>>,\n}\n\nfn main() {\n let leaf = Rc::new(Node {\n value: 3,\n parent: RefCell::new(Weak::new()),\n children: RefCell::new(vec![]),\n });\n\n println!(\n \"leaf strong = {}, weak = {}\",\n Rc::strong_count(&leaf),\n Rc::weak_count(&leaf),\n );\n\n {\n let branch = Rc::new(Node {\n value: 5,\n parent: RefCell::new(Weak::new()),\n children: RefCell::new(vec![Rc::clone(&leaf)]),\n });\n\n *leaf.parent.borrow_mut() = Rc::downgrade(&branch);\n\n println!(\n \"branch strong = {}, weak = {}\",\n Rc::strong_count(&branch),\n Rc::weak_count(&branch),\n );\n\n println!(\n \"leaf strong = {}, weak = {}\",\n Rc::strong_count(&leaf),\n Rc::weak_count(&leaf),\n );\n }\n\n println!(\"leaf parent = {:?}\", leaf.parent.borrow().upgrade());\n println!(\n \"leaf strong = {}, weak = {}\",\n Rc::strong_count(&leaf),\n Rc::weak_count(&leaf),\n );\n}\n```","slug":"rust/rust-06-smart-pointer","published":1,"updated":"2023-05-03T07:31:43.613Z","comments":1,"layout":"post","photos":[],"link":"","_id":"clk1e4wps000j6hsj1nk1429h","content":"
Overview
The most common kind of pointer in Rust is a reference (borrow but not own) Smart pointers, on the other hand, are data structures that not only act like a pointer but also have additional metadata and capabilities. references are pointers that only borrow data; in contrast, in many cases, smart pointers own the data they point to.