├── .github ├── dependabot.yml └── workflows │ └── publish.yml ├── .gitignore ├── .obsidian ├── app.json ├── appearance.json ├── core-plugins.json ├── hotkeys.json └── workspace ├── LICENSE ├── Makefile ├── README.md ├── assets ├── approx-combination │ ├── approx-combination.py │ ├── binomial-normal-margin.png │ └── binomial-normal.png ├── binary-tree-count │ ├── 3-node-binary-trees.excalidraw.png │ └── left-right-sub-tree.excalidraw.png ├── openacid │ ├── qrcode-hori.jpg │ └── qrcode-text.png ├── sorted-strings-range-filter │ └── str-demo.excalidraw.png └── tokio-blocking-hangs │ └── hang.excalidraw.png ├── c-playground └── macro_for_each │ └── macro_for_each.c ├── journals └── 2022_12_23.md ├── link-check-config.json ├── logseq ├── config.edn └── custom.css ├── pages ├── DOING.md ├── Tips.md ├── Today's tip.md ├── algorithm-vector-index.md ├── assembly.md ├── bash.md ├── c-programming.md ├── chatGPT-util.md ├── clang.md ├── contents.md ├── deterministic.md ├── gcc.md ├── git.md ├── github.md ├── go-programming.md ├── hash.md ├── pyhton.md ├── reading.md ├── rust-programming.md ├── rust-search-engine.md ├── rust-serialization.md ├── rust-unstable-features.md ├── serverless.md ├── tmux.md ├── utils.md ├── vercel.md ├── web-design.md ├── web-testing.md └── z-order.md ├── rust-benchmark ├── .gitignore ├── Cargo.toml ├── benches │ └── vec-push.rs └── rust-toolchain ├── rust-playground ├── .gitignore ├── Cargo.toml ├── benches │ └── bench-vec-push.rs ├── rust-toolchain ├── src │ └── bin │ │ ├── 100013-gat-self---a-bounds-break-some-async-blocks-with-impl-trait.rs │ │ ├── async-fn-as-generic-pin-box.rs │ │ ├── async-fn-as-generic.rs │ │ ├── async_read_buf_chunk_size.rs │ │ ├── borrow-of-moved-reborrow.rs │ │ ├── box-stream-to-impl-void-error-2.rs │ │ ├── box-stream-to-impl-void-lifetime-error.rs │ │ ├── box-trait-object-fat-pointer.rs │ │ ├── bsearch-branchless.rs │ │ ├── bug-send-higher-ranked-lifetime.rs │ │ ├── cell-test.rs │ │ ├── cfg-test.rs │ │ ├── compatible-error.rs │ │ ├── either.rs │ │ ├── enum-size.rs │ │ ├── framed-async-read-to-stream.rs │ │ ├── future-now-or-never.rs │ │ ├── futures-async-stream--try_stream.rs │ │ ├── gat-future-iskyzh.rs │ │ ├── gat-future-multi-lifetime.rs │ │ ├── get-stack-pos-unsafe.rs │ │ ├── get_type_macro.rs │ │ ├── gg.rs │ │ ├── impl-by-trait.rs │ │ ├── impl-trait-for-option-generic-conflict.rs │ │ ├── impl-trait-for-option-generic-solution.rs │ │ ├── iter-ref-self.rs │ │ ├── macro_kv_default.rs │ │ ├── map-api-error-2-lifetime.rs │ │ ├── map-api-error-map-api-need-2-param.rs │ │ ├── map-api-lifetime-me-outlive-f.rs │ │ ├── map-api-lifetime-try-ref-mut.rs │ │ ├── map-api-lifetime-weird-error.rs │ │ ├── map-api-lifetime-writable-error.rs │ │ ├── map-api-lifetime.rs │ │ ├── map-api-send-cause-not-general-err.rs │ │ ├── map-api-simplified.rs │ │ ├── match-arm-stack-size.rs │ │ ├── min-specialization.rs │ │ ├── mixin.rs │ │ ├── mut-ref-to-ref-require-lifetime-constraint.rs │ │ ├── non-implementable-trait-method.rs │ │ ├── not-send.rs │ │ ├── pattern-in-arg.rs │ │ ├── pin-a-value.rs │ │ ├── ref-vs-ref-keyword.rs │ │ ├── return-position-2.rs │ │ ├── return-position.rs │ │ ├── return_position_impl_trait_in_trait-stable.rs │ │ ├── serde-bound.rs │ │ ├── specialization-with-autoref.rs │ │ ├── specialization.rs │ │ ├── static-param.rs │ │ ├── stream-map.rs │ │ ├── thread_local_attr_not_dropped.rs │ │ ├── thread_local_macro_drop.rs │ │ ├── tokio-shutdown.rs │ │ ├── tokio-unbounded-recv-select.rs │ │ ├── try-logcall.rs │ │ ├── x.rs │ │ ├── y.rs │ │ ├── yy.rs │ │ └── z.rs ├── t-cfg │ ├── .cargo │ │ └── config.toml │ ├── .gitignore │ ├── Cargo.toml │ └── src │ │ └── main.rs ├── t-detect-nightly │ ├── .gitignore │ ├── Cargo.toml │ ├── build.rs │ └── src │ │ └── main.rs ├── t-monoio │ ├── .gitignore │ ├── Cargo.toml │ └── src │ │ ├── bin │ │ ├── cross-rt-join.rs │ │ └── foo.rs │ │ ├── main.rs │ │ └── monoio-main.rs └── t-protobuf │ ├── .gitignore │ ├── Cargo.toml │ ├── build.rs │ ├── proto │ └── meta.proto │ └── src │ ├── lib.rs │ └── main.rs ├── scripts ├── comments.html └── img-add-margin.sh ├── snippet ├── README.md └── rust │ ├── dup-file │ ├── .gitignore │ ├── Cargo.toml │ └── src │ │ └── main.rs │ ├── new-cargo │ ├── pb-oneof-forward-compat │ ├── build.rs │ └── proto │ │ └── foo.proto │ └── serde-msgpack-bincode │ ├── .gitignore │ ├── Cargo.toml │ └── src │ └── main.rs └── tips ├── Assembly register in x86.md ├── Catalan number proof: generating function.md ├── Catalan number 卡塔兰数.md ├── Chebyshev inequality 切比雪夫不等式.md ├── C语言宏实现循环.md ├── Derangement 错排.md ├── Markov inequality 马尔可夫不等式.md ├── Probability basic.md ├── Rust Cargo dependency 分类.md ├── Rust bincode msgpack 向后兼容性比较.md ├── Rust branchless bsearch.md ├── Rust branchless heap sort.md ├── Rust bug.md ├── Rust detect nightly.md ├── Rust ref vs ref-keyword.md ├── Rust sealed trait.md ├── Rust serde 指定 bound.md ├── Rust subtyping and variance.md ├── Rust unstable min_specialization.md ├── Rust 中 trait 的 lifetime 使用示例.md ├── Rust 中为泛型实现 trait 时 conflicting implementation 错误的解决方案.md ├── Rust 中使用 attribute 定义的 thread_local 的 drop 方法不被调用.md ├── Rust 中对enum size的优化.md ├── Rust 中引用旧版本的代码.md ├── Rust 中每个 match 分支都占用栈上空间.md ├── Rust 从 mut ref 得到 ref 需要额外的 lifetime 限制.md ├── Rust 使用Fn作为泛型无法约束lifetime.md ├── Rust 函数参数 pattern.md ├── Rust 创建 Stream Sink.md ├── Rust 实用文件log创建.md ├── Rust 遇到泛型参数手动 reborrow mut ref.md ├── Tokio 中 hang 死所有 worker 的方法.md ├── databend └── profiling │ ├── 174307263-a2c9bbe6-e417-48b7-bf4d-cbbbaad03a6e.png │ ├── 204963954-f6eacf10-d8bd-4469-9c8d-7d30955f1a78.png │ └── profiling-databend.md ├── jemalloc ├── jemalloc-guide.md ├── jemalloc-tips.md └── jemalloc-tuning.md ├── latex-reference.md ├── latex-util.md ├── life ├── 急性肠胃炎.md └── 隔音-2024-08 │ ├── imgs │ ├── 20cm实物图.jpg │ ├── 价格表.jpg │ ├── 安装步骤.png │ ├── 超薄减震器.jpg │ ├── 超薄实物图.jpg │ └── 超薄食物细节.jpg │ ├── 安装步骤.png │ └── 隔音-2024-08.md ├── lldb └── lldb默认拦截signal, 需要设置pass.md ├── math ├── complex-analysis │ └── Complex conjugate root theorem 共轭复根定理.md ├── math-combinatorics.md ├── math-complex-analysis.md ├── math-field.md ├── math-group.md ├── math-probability.md ├── math.md ├── mid-school-geometry │ ├── DEF 为正三角形 AD=BF=CE 求证 ABC为正三角形.md │ ├── Makefile │ ├── question-and-answer-cropped.jpg │ ├── question-and-answer-cropped.pdf │ ├── question-and-answer.pdf │ ├── question-and-answer.tex │ ├── question-cropped.pdf │ ├── question.pdf │ └── question.tex └── order-dimension │ ├── infinite-poset-2d@math@order-dimension.md │ ├── infinite-poset-3d@math@order-dimension.md │ ├── infinite-poset-4d@math@order-dimension.md │ └── order-dimension@math.md ├── mdbook └── mdbook.md ├── n 节点 binary-tree 的个数.md ├── openssl └── openssl.md ├── raft └── Inconsistent partial order pseudo time in Raft.md ├── rust ├── Rust String tips.md ├── Rust precise capture in impl Trait.md ├── Rust sealed trait method.md ├── Rust 中 static BoxStream 丢失信息导致 higher rank lifetime error.md ├── Rust 利用 autoref 实现 specialization.md ├── rust-learn │ └── rust-learn.md └── rust.md ├── web-page-building ├── Tailwindcss colors.md └── web-page-building.md ├── 为 排序字符串 创建 range filter.md ├── 使用正态分布近似计算组合数.md ├── 圆偏振光3d眼镜.md ├── 存储 n 节点的 binary-tree 最少只需 2n bit.md ├── 微信公众号.md ├── 用 CloudFlare R2 作为个人存储.md └── 语言改变命运.md /.github/dependabot.yml: -------------------------------------------------------------------------------- 1 | version: 2 2 | updates: 3 | - package-ecosystem: "github-actions" 4 | directory: "/" 5 | schedule: 6 | interval: "daily" 7 | -------------------------------------------------------------------------------- /.github/workflows/publish.yml: -------------------------------------------------------------------------------- 1 | name: Publish 2 | 3 | concurrency: 4 | group: ${{ github.workflow }}-${{ github.ref }} 5 | cancel-in-progress: true 6 | 7 | on: 8 | push: 9 | branches: 10 | - main 11 | workflow_dispatch: 12 | 13 | jobs: 14 | build: 15 | runs-on: ubuntu-latest 16 | 17 | steps: 18 | - uses: actions/checkout@v3 19 | 20 | - name: Logseq Publish 21 | # Using main branch to reproduce https://github.com/pengx17/logseq-publish/issues/8 22 | # Should switch back to stable release after this issue fixed. 23 | uses: pengx17/logseq-publish@main 24 | with: 25 | dest: www 26 | # disable building a trace.zip 27 | trace: false 28 | 29 | - name: add a nojekyll file 30 | # to make sure asset paths are correctly identified 31 | # -- ref: https://github.com/pengx17/logseq-publish#usage 32 | run: touch $GITHUB_WORKSPACE/www/.nojekyll 33 | 34 | # Ideas borrowed from https://logseq.abosen.top/#/page/%E9%85%8D%E7%BD%AE%20logseq%20%E8%87%AA%E5%8A%A8%E5%8F%91%E5%B8%83%E7%9B%B8%E5%85%B3%E6%B5%81%E7%A8%8B 35 | - name: Inject comments 36 | run: sed -i "s@@$( cat scripts/comments.html | tr '\n' ' ' | sed 's@&@\\&@g' )@" www/index.html 37 | 38 | - name: Deploy 🚀 39 | uses: JamesIves/github-pages-deploy-action@v4 40 | with: 41 | branch: gh-pages 42 | folder: www 43 | clean: true 44 | # do not keep built branch history 45 | single-commit: true 46 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | /logseq/bak 2 | 3 | 4 | .DS_Store 5 | -------------------------------------------------------------------------------- /.obsidian/app.json: -------------------------------------------------------------------------------- 1 | { 2 | "legacyEditor": false, 3 | "livePreview": true, 4 | "alwaysUpdateLinks": false 5 | } -------------------------------------------------------------------------------- /.obsidian/appearance.json: -------------------------------------------------------------------------------- 1 | { 2 | "theme": "moonstone" 3 | } -------------------------------------------------------------------------------- /.obsidian/core-plugins.json: -------------------------------------------------------------------------------- 1 | [ 2 | "file-explorer", 3 | "global-search", 4 | "switcher", 5 | "graph", 6 | "backlink", 7 | "page-preview", 8 | "note-composer", 9 | "command-palette", 10 | "editor-status", 11 | "markdown-importer", 12 | "word-count", 13 | "open-with-default-app", 14 | "file-recovery" 15 | ] -------------------------------------------------------------------------------- /.obsidian/hotkeys.json: -------------------------------------------------------------------------------- 1 | {} -------------------------------------------------------------------------------- /.obsidian/workspace: -------------------------------------------------------------------------------- 1 | { 2 | "main": { 3 | "id": "01245237610f2577", 4 | "type": "split", 5 | "children": [ 6 | { 7 | "id": "0c62626a566524f1", 8 | "type": "leaf", 9 | "state": { 10 | "type": "markdown", 11 | "state": { 12 | "file": "tips/approx-combination.md", 13 | "mode": "source", 14 | "source": false 15 | } 16 | } 17 | } 18 | ], 19 | "direction": "vertical" 20 | }, 21 | "left": { 22 | "id": "af5162aa9b383756", 23 | "type": "split", 24 | "children": [ 25 | { 26 | "id": "6a2627f0da540e43", 27 | "type": "tabs", 28 | "children": [ 29 | { 30 | "id": "018f02fb2cc30e61", 31 | "type": "leaf", 32 | "state": { 33 | "type": "file-explorer", 34 | "state": {} 35 | } 36 | }, 37 | { 38 | "id": "fa3f0a7df8c53493", 39 | "type": "leaf", 40 | "state": { 41 | "type": "search", 42 | "state": { 43 | "query": "", 44 | "matchingCase": false, 45 | "explainSearch": false, 46 | "collapseAll": false, 47 | "extraContext": false, 48 | "sortOrder": "alphabetical" 49 | } 50 | } 51 | } 52 | ] 53 | } 54 | ], 55 | "direction": "horizontal", 56 | "width": 300 57 | }, 58 | "right": { 59 | "id": "e5746e952b51ff58", 60 | "type": "split", 61 | "children": [ 62 | { 63 | "id": "2e4e4f29b25d54a4", 64 | "type": "tabs", 65 | "children": [ 66 | { 67 | "id": "9fde0a28c9dd2acd", 68 | "type": "leaf", 69 | "state": { 70 | "type": "backlink", 71 | "state": { 72 | "file": "tips/approx-combination.md", 73 | "collapseAll": false, 74 | "extraContext": false, 75 | "sortOrder": "alphabetical", 76 | "showSearch": false, 77 | "searchQuery": "", 78 | "backlinkCollapsed": false, 79 | "unlinkedCollapsed": true 80 | } 81 | } 82 | } 83 | ] 84 | } 85 | ], 86 | "direction": "horizontal", 87 | "width": 300, 88 | "collapsed": true 89 | }, 90 | "active": "0c62626a566524f1", 91 | "lastOpenFiles": [ 92 | "tips/approx-combination.md" 93 | ] 94 | } -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | MIT License 2 | 3 | Copyright (c) 2021 张炎泼 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. 22 | -------------------------------------------------------------------------------- /Makefile: -------------------------------------------------------------------------------- 1 | check-local-link: 2 | find ./tips/ -name \*.md -print0 | xargs -0 -n1 markdown-link-check -c link-check-config.json 3 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # XP's tips collection 2 | 3 | I'm too stupid to remember things. I have to write things down for the future me. 4 | And in the hope that they will help anyone who wish to learn these things, I've tried to make these tips less academic. 5 | 6 | - View it online: https://drmingdrmer.github.io/tips/ . 7 | - Or view it on github: https://github.com/drmingdrmer/tips/tree/main/tips . 8 | 9 | This site is [logseq](https://logseq.com/) based, and is published online with [logseq-github-action](https://github.com/pengx17/logseq-publish). 10 | 11 | 12 | 13 | **Directory layout**: 14 | 15 | 16 | - `/tips`: well-formatted articles. 17 | 18 | - `/pages`, `/assets`, `/journals`, `logseq` and `/draws` are [logseq](https://logseq.com/) maintained 19 | dir. 20 | 21 | -------------------------------------------------------------------------------- /assets/approx-combination/approx-combination.py: -------------------------------------------------------------------------------- 1 | import math 2 | 3 | def facto(n): 4 | if n == 1: 5 | return 1 6 | return n*facto(n-1) 7 | 8 | def combi(n, m): 9 | return facto(n) / facto(m) / facto(n-m) 10 | 11 | def approx_combi(n, m): 12 | u = n * .5 13 | sig = (n*.5*.5) ** 0.5 14 | 15 | power = - (m-u) ** 2 / 2 / sig / sig 16 | return 1.0 / (sig * ((2*math.pi)**.5)) * (math.e ** power) * (2**n) 17 | 18 | n, m = 12, 3 19 | print("Approximate combination number C({}, {}) by normal distribution:".format(n, m)) 20 | print("accurate, approximated:") 21 | print(combi(n, m), '%.3f' % approx_combi(n, m)) 22 | -------------------------------------------------------------------------------- /assets/approx-combination/binomial-normal-margin.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/drmingdrmer/tips/047f274864fb33ac7f6da89eba8e806ac6edb49c/assets/approx-combination/binomial-normal-margin.png -------------------------------------------------------------------------------- /assets/approx-combination/binomial-normal.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/drmingdrmer/tips/047f274864fb33ac7f6da89eba8e806ac6edb49c/assets/approx-combination/binomial-normal.png -------------------------------------------------------------------------------- /assets/binary-tree-count/3-node-binary-trees.excalidraw.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/drmingdrmer/tips/047f274864fb33ac7f6da89eba8e806ac6edb49c/assets/binary-tree-count/3-node-binary-trees.excalidraw.png -------------------------------------------------------------------------------- /assets/binary-tree-count/left-right-sub-tree.excalidraw.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/drmingdrmer/tips/047f274864fb33ac7f6da89eba8e806ac6edb49c/assets/binary-tree-count/left-right-sub-tree.excalidraw.png -------------------------------------------------------------------------------- /assets/openacid/qrcode-hori.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/drmingdrmer/tips/047f274864fb33ac7f6da89eba8e806ac6edb49c/assets/openacid/qrcode-hori.jpg -------------------------------------------------------------------------------- /assets/openacid/qrcode-text.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/drmingdrmer/tips/047f274864fb33ac7f6da89eba8e806ac6edb49c/assets/openacid/qrcode-text.png -------------------------------------------------------------------------------- /assets/sorted-strings-range-filter/str-demo.excalidraw.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/drmingdrmer/tips/047f274864fb33ac7f6da89eba8e806ac6edb49c/assets/sorted-strings-range-filter/str-demo.excalidraw.png -------------------------------------------------------------------------------- /assets/tokio-blocking-hangs/hang.excalidraw.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/drmingdrmer/tips/047f274864fb33ac7f6da89eba8e806ac6edb49c/assets/tokio-blocking-hangs/hang.excalidraw.png -------------------------------------------------------------------------------- /c-playground/macro_for_each/macro_for_each.c: -------------------------------------------------------------------------------- 1 | // Implement for-each loop with preprocessor 2 | // Usage: 3 | // gcc -E macro_for_each.c 4 | 5 | #define EVAL(...) EVAL1(EVAL1(EVAL1(__VA_ARGS__))) 6 | #define EVAL1(...) EVAL2(EVAL2(EVAL2(__VA_ARGS__))) 7 | #define EVAL2(...) EVAL3(EVAL3(EVAL3(__VA_ARGS__))) 8 | #define EVAL3(...) EVAL4(EVAL4(EVAL4(__VA_ARGS__))) 9 | #define EVAL4(...) EVAL5(EVAL5(EVAL5(__VA_ARGS__))) 10 | #define EVAL5(...) __VA_ARGS__ 11 | 12 | #define arg1(a, ...) a 13 | #define shift(a, ...) __VA_ARGS__ 14 | 15 | #define __empty_ 1 16 | #define arg3(a1, a2, a3, ...) a3 17 | /* #define is_empty(ph, ...) arg3(ph, ##__VA_ARGS__, 1, 0) */ 18 | #define is_empty(ph, ...) ph, ##__VA_ARGS__, 1 19 | 20 | #define empty() 21 | #define defer(id) id empty() 22 | #define obstruct(...) __VA_ARGS__ defer(empty)() 23 | 24 | #define CAT(a, ...) PRIMITIVE_CAT(a, __VA_ARGS__) 25 | #define PRIMITIVE_CAT(a, ...) a ## __VA_ARGS__ 26 | 27 | #define COMPL(b) PRIMITIVE_CAT(COMPL_, b) 28 | #define COMPL_0 1 29 | #define COMPL_1 0 30 | 31 | #define IIF(cond) CAT(IIF_,cond) 32 | #define IIF_0(t, f) f 33 | #define IIF_1(t, f) t 34 | 35 | #define NOT(x) CHECK(PRIMITIVE_CAT(NOT_, x)) 36 | #define NOT_0 PROBE(~) 37 | 38 | #define BOOL(x) COMPL(NOT(x)) 39 | #define IF(c) IIF(BOOL(c)) 40 | 41 | #define CHECK_N(x, n, ...) n 42 | #define CHECK(...) CHECK_N(__VA_ARGS__, 0,) 43 | #define PROBE(x) x, 1, 44 | 45 | #define EAT(...) 46 | #define EXPAND(...) __VA_ARGS__ 47 | #define WHEN(c) IF(c)(EXPAND, EAT) 48 | 49 | #define IS_PAREN(x) CHECK(IS_PAREN_PROBE x) 50 | #define IS_PAREN_PROBE(...) PROBE(~) 51 | 52 | #define no_args_x(...) #__VA_ARGS__ 53 | #define no_args(...) 0 EVAL(no_args_(__VA_ARGS__, ())) 54 | 55 | #define no_args_(c, ...) \ 56 | IIF(BOOL(IS_PAREN(c)))( , \ 57 | + 1 \ 58 | obstruct(no_args_xx)()(__VA_ARGS__) \ 59 | ) 60 | 61 | #define no_args_xx() no_args_ 62 | 63 | #define for_each(statement, ...) EVAL(foreach(statement, __VA_ARGS__, ~)) 64 | 65 | #define foreach(statement, c, ...) \ 66 | IIF(BOOL(IS_PAREN(c)))( \ 67 | statement c \ 68 | obstruct(foreach_xx)()(statement, __VA_ARGS__) \ 69 | , \ 70 | ) 71 | 72 | #define foreach_xx() foreach 73 | 74 | // --- Example: 75 | 76 | #define handle_error(m) if (m == err) { \ 77 | log_error("error is: %s", #m); \ 78 | return -1; \ 79 | } 80 | 81 | for_each(handle_error, (a), (b), (c)); 82 | 83 | // --- Playground, ignore it: 84 | 85 | int foo() { 86 | /* 87 | * # define elts (a), (b), (c) 88 | * # define handle_error(m) if (m == err) { \ 89 | * log_error("error is: %s", #m); \ 90 | * return -1; \ 91 | * } 92 | * 93 | * for_each(handle_error, elts); 94 | */ 95 | 96 | /* 97 | * int x = arg1(); 98 | * x = IIF(BOOL(IS_PAREN(())))(a,b); 99 | * x = is_empty(x); 100 | * x = is_empty(); 101 | * 102 | * x = CHECK(1); 103 | * x = CHECK(yy); 104 | * x = CHECK(); 105 | * x = CHECK(PROBE(~)); 106 | */ 107 | 108 | /* x = WHEN(IS_PAREN(a))(1,2); */ 109 | 110 | /* 111 | * for_each(printf, 112 | * (a, 1), 113 | * (a, 1), 114 | * (a, 1), 115 | * (a, 1), 116 | * (b), 117 | * (c) 118 | * ); 119 | */ 120 | 121 | nr = no_args(1,2,3,4); 122 | } 123 | -------------------------------------------------------------------------------- /journals/2022_12_23.md: -------------------------------------------------------------------------------- 1 | - [[approx-combination]] 2 | - -------------------------------------------------------------------------------- /link-check-config.json: -------------------------------------------------------------------------------- 1 | { 2 | "ignorePatterns": [ 3 | { 4 | "pattern": "^http" 5 | } 6 | ] 7 | } 8 | -------------------------------------------------------------------------------- /logseq/custom.css: -------------------------------------------------------------------------------- 1 | /* remove the padding space above and below code block; top:18->0; bottom:62->44 */ 2 | .CodeMirror-scroll { 3 | padding-top: 0px; 4 | padding-bottom: 0px; 5 | 6 | margin-bottom: 0px; 7 | 8 | position: static; 9 | } 10 | 11 | /* the original margin-bottom is a negative value, which cause the code block a bit higher than its container, and there is a unnecessary virtical scroll */ 12 | .CodeMirror-sizer { 13 | margin-bottom: 0px !important; 14 | } 15 | 16 | /* use smaller code font size 14->12 */ 17 | .CodeMirror pre.CodeMirror-line 18 | { 19 | font-size: 12px; 20 | } 21 | -------------------------------------------------------------------------------- /pages/Tips.md: -------------------------------------------------------------------------------- 1 | - -------------------------------------------------------------------------------- /pages/Today's tip.md: -------------------------------------------------------------------------------- 1 | - {{embed [[Rust 中每个 match 分支都占用栈上空间]] }} 2 | - **All Tips**: [[Tips]] -------------------------------------------------------------------------------- /pages/algorithm-vector-index.md: -------------------------------------------------------------------------------- 1 | - HNSW算法----Hierarchcal Navigable Small World graphs,第一贡献者:Y.Malkov(俄) 2 | https://blog.csdn.net/sinat_28704977/article/details/86605331 3 | - -------------------------------------------------------------------------------- /pages/assembly.md: -------------------------------------------------------------------------------- 1 | - 2 | - -------------------------------------------------------------------------------- /pages/bash.md: -------------------------------------------------------------------------------- 1 | - count different lines 2 | `diff -y --suppress-common-lines a b | wc -l` -------------------------------------------------------------------------------- /pages/c-programming.md: -------------------------------------------------------------------------------- 1 | - https://github.com/swansontec/map-macro 2 | - -------------------------------------------------------------------------------- /pages/chatGPT-util.md: -------------------------------------------------------------------------------- 1 | - A simple common-line interface for ChatGPT API 2 | https://github.com/fuyufjh/heygpt 3 | - #### GPT-4 Turbo搭建教程 4 | https://doc.muluhub.com/docs/gpt4turbo/GPT4-Turbo 5 | https://openai-hk.com/docs/getting-started.html 6 | - 7 | - -------------------------------------------------------------------------------- /pages/clang.md: -------------------------------------------------------------------------------- 1 | - Generate assembly; for `x86_64`, in intel syntax: `clang -masm=intel -arch x86_64 -S c.c` 2 | Or: `clang++ -S -mllvm --x86-asm-syntax=intel test.cpp` 3 | https://stackoverflow.com/questions/10990018/how-to-generate-assembly-code-with-clang-in-intel-syntax 4 | - Clang cross compilation: 5 | https://clang.llvm.org/docs/CrossCompilation.html -------------------------------------------------------------------------------- /pages/contents.md: -------------------------------------------------------------------------------- 1 | - I'm Zhang Yanpo. Friends just call me XP. 2 | - Source code of this site(XP's tips): https://github.com/drmingdrmer/tips 3 | - XP's blog: https://blog.openacid.com/ 4 | - 5 | - [[Today's tip]] 6 | - 7 | - [[DOING]] 8 | - {{query #LATER }} 9 | query-sort-by:: block 10 | query-table:: true 11 | query-sort-desc:: true 12 | - [[reading]] 13 | - [[openraft]] 14 | - {{query #read }} 15 | query-table:: true 16 | query-sort-by:: block 17 | query-sort-desc:: false 18 | - 19 | - **Topics:** 20 | query-table:: true 21 | - 📁 ⭐️ [[rust]] 22 | - 📁 [[math]] 23 | - [[漫画]] 24 | - [[CG-util]] 25 | - 📁 [[life]] 26 | - [[ai]] 27 | - [[ascii-util]] 28 | - [[assembly]] 29 | - [[algorithm-vector-index]] 30 | - [[bash]] 31 | - [[bloom-filter-etc]] 32 | - [[daily]] 33 | - [[databend]] 34 | - [[deterministic]] 35 | - [[distributed-system]] 36 | - [[cache]] 37 | - [[c-programming]] 38 | - [[chatGPT-util]] 39 | - [[clang]] 40 | - [[ffmpeg]] 41 | - [[gcc]] 42 | - [[gfw]] 43 | - [[git]] 44 | - [[github]] 45 | - [[go-programming]] 46 | - [[ide]] 47 | - [[jetbrains]] 48 | - [[hash]] 49 | - [[jemalloc]] 50 | - [[latex]] 51 | - [[learn]] 52 | - [[logseq-resrouce]] 53 | - [[markdown-editor]] 54 | - [[markup languages]] 55 | - 56 | - [[mdbook]] 57 | - [[online-drawing]] 58 | - [[openai]] 59 | - [[openssl]] 60 | - [[productivity]] 61 | - [[protobuf]] 62 | - [[pyhton]] 63 | - [[serverless]] 64 | - [[tmux]] 65 | - [[utils]] 66 | - [[vercel]] 67 | - [[web-design]] 68 | - [[web-testing]] 69 | - [[zellij]] 70 | - [[微信公众号]] 71 | - [[日常]] // == daily 72 | - [[自动铅笔]] 73 | - [[乱写的]] 74 | - [[playground]] 75 | - [[Tips]] 76 | - [[Friends]] 77 | - -------------------------------------------------------------------------------- /pages/deterministic.md: -------------------------------------------------------------------------------- 1 | - **madsim** 2 | Magical Deterministic Simulator for distributed systems in Rust. 3 | https://github.com/madsim-rs/madsim -------------------------------------------------------------------------------- /pages/gcc.md: -------------------------------------------------------------------------------- 1 | - Generate assembly: for ARM platform `gcc -march=armv7-a -S c.c` -------------------------------------------------------------------------------- /pages/git.md: -------------------------------------------------------------------------------- 1 | - Git Internals 2 | - Git internal objects: create object, tree, 3 | https://git-scm.com/book/en/v2/Git-Internals-Git-Objects 4 | - Git packfiles 5 | https://git-scm.com/book/en/v2/Git-Internals-Packfiles 6 | - examine pack file content: 7 | `git verify-pack -v .git/objects/pack/pack-978e03944f5c581011e6998cd0e9e30000905586.idx` 8 | - Git Refspec 9 | https://git-scm.com/book/en/v2/Git-Internals-The-Refspec 10 | - Git Transfer protocols 11 | https://git-scm.com/book/en/v2/Git-Internals-Transfer-Protocols 12 | - Setup proxy for https remote: 13 | `export http_proxy="http://"; export https_proxy="http://"` 14 | `git config --global http.proxy http://` `git config --global https.proxy http://` -------------------------------------------------------------------------------- /pages/github.md: -------------------------------------------------------------------------------- 1 | - 2 | - Creates GitHub releases for pushed tags, with the commit log as release body https://github.com/fregante/release-with-changelog 3 | - 4 | - Useful badges: 5 | ``` 6 | [![Discord Chat](https://img.shields.io/discord/1180545690976391251?logo=discord&style=flat-square)](https://discord.gg/fFPsTqYqUg) 7 | [![Crates.io](https://img.shields.io/crates/v/validit.svg)](https://crates.io/crates/validit) 8 | [![docs.rs](https://docs.rs/validit/badge.svg)](https://docs.rs/validit) 9 | ![Crates.io](https://img.shields.io/crates/d/validit.svg) 10 | ![Crates.io](https://img.shields.io/crates/dv/validit.svg) 11 | 12 | ``` 13 | See: https://shields.io/badges/discord 14 | - 15 | - ### Github action 16 | - **cache** caching dependencies and build outputs to improve workflow execution time 17 | https://github.com/actions/cache 18 | Used by databend: https://github.com/datafuselabs/databend/blob/aa54ea223932087a7b1a06fb690ed780aad8ca5f/.github/workflows/links.yml 19 | Support various languages: https://github.com/actions/cache/blob/main/examples.md#rust---cargo 20 | Cache strategies: https://github.com/actions/cache/blob/main/caching-strategies.md 21 | - **cache doc**: https://docs.github.com/en/actions/using-workflows/caching-dependencies-to-speed-up-workflows 22 | - Automatically commit changes made in your workflow run directly to your repo: https://github.com/EndBug/add-and-commit 23 | - ``` 24 | - uses: baptiste0928/cargo-install@v1 25 | with: 26 | crate: typos-cli 27 | args: --locked 28 | cache-key: typos-check 29 | ``` -------------------------------------------------------------------------------- /pages/go-programming.md: -------------------------------------------------------------------------------- 1 | - https://github.com/bits-and-blooms/bitset -------------------------------------------------------------------------------- /pages/hash.md: -------------------------------------------------------------------------------- 1 | - siphash 2 | - murmurhash2 3 | - city 4 | - 5 | - ### Rendezvous hashing 6 | https://en.wikipedia.org/wiki/Rendezvous_hashing 7 | - -------------------------------------------------------------------------------- /pages/pyhton.md: -------------------------------------------------------------------------------- 1 | - An extremely fast Python linter, written in Rust. 2 | https://github.com/charliermarsh/ruff -------------------------------------------------------------------------------- /pages/reading.md: -------------------------------------------------------------------------------- 1 | - https://www.fpcomplete.com/blog/philosophies-rust-haskell/ 2 | - https://github.com/bheisler/criterion.rs 3 | - <<蝇王>> 小说 威廉戈尔丁 4 | - 5 | - 6 | - 7 | - {{query #read}} 8 | query-table:: true 9 | title:: reading 10 | - 11 | - 用 Rust 做类型体操 (上篇) 12 | https://www.skyzh.dev/blog/2022-01-22-rust-type-exercise-in-database-executors/ 13 | - Parse, don’t validate 14 | https://lexi-lambda.github.io/blog/2019/11/05/parse-don-t-validate/ 15 | - crate validit 实际上是 refine们他 type -- by leiysky 16 | https://en.wikipedia.org/wiki/Refinement_type 17 | 类似的也有: xxchan 提供, 给函数加proc_macro 18 | https://docs.rs/contracts/latest/contracts/ 19 | - 20 | - Writing a file system from scratch in Rust 21 | twitter https://twitter.com/eatonphil/status/1731417469204545606 22 | - 23 | - **seaweedfs replication** 24 | https://github.com/seaweedfs/seaweedfs/wiki/Replication#fix-replication 25 | - **math** 数学 26 | - dense set 稠密集 27 | https://zhuanlan.zhihu.com/p/348875663 28 | - 29 | - TLA 30 | - pingcap/tla-plus 31 | https://github.com/pingcap/tla-plus 32 | - etcd TLA+ spec 33 | https://github.com/etcd-io/raft/issues/111 34 | - TLA+ specification for gryadka: [https://github.com/gryadka/js](https://github.com/gryadka/js) 35 | https://medium.com/@grogepodge/tla-specification-for-gryadka-c80cd625944e 36 | https://gist.github.com/grogers0/c7e87f9dfe58c6070b19db9d3c073b72#file-gryadkacasregister-tla-L50 37 | - #### Log paxos 38 | https://github.com/Cjen1/consensus-tlaplus/tree/main/LogPaxos 39 | - #### Decentralized Thoughts 40 | https://decentralizedthoughts.github.io/ 41 | - simplifying-raft-with-chaining 42 | https://decentralizedthoughts.github.io/2021-07-17-simplifying-raft-with-chaining/ 43 | - distributed-consensus-made-simple-for-real-this-time 44 | https://decentralizedthoughts.github.io/2021-09-30-distributed-consensus-made-simple-for-real-this-time/ 45 | - 46 | - #### Learned index 47 | https://zhuanlan.zhihu.com/p/536461846?utm_campaign=shareopn&utm_medium=social&utm_oi=1079513764176629760&utm_psn=1723814674175578112&utm_source=wechat_session 48 | https://zhuanlan.zhihu.com/p/537075200?utm_campaign=shareopn&utm_medium=social&utm_oi=1079513764176629760&utm_psn=1723805021047779328&utm_source=wechat_session 49 | https://zhuanlan.zhihu.com/p/625142215?utm_campaign=shareopn&utm_medium=social&utm_oi=1079513764176629760&utm_psn=1723818324801138688&utm_source=wechat_session -------------------------------------------------------------------------------- /pages/rust-programming.md: -------------------------------------------------------------------------------- 1 | - [[rust-unstable-features]] 2 | - 线上书: 3 | `<< The Rustonomicon >>`: The Dark Arts of Advanced and Unsafe Rust Programming 4 | https://doc.rust-lang.org/nomicon/intro.html 5 | https://github.com/rust-lang/nomicon 6 | - **Env variables** 7 | https://web.mit.edu/rust-lang_v1.25/arch/amd64_ubuntu1404/share/doc/rust/html/cargo/reference/environment-variables.html 8 | - cargo-run 9 | https://doc.rust-lang.org/cargo/commands/cargo-run.html#cargo-run1 10 | - What's unwind-safe? 11 | - list enabled features when compiling: `cargo tree -e features` 12 | - skip boundary check; Informs the optimizer that a condition is always true. https://doc.rust-lang.org/core/intrinsics/fn.assume.html 13 | - flatten_error? flatten result? 14 | - crate num and num-traits: define traits for numbers 15 | num depends on num-traits 16 | https://docs.rs/num/0.4.0/num/ 17 | - std::ops::Mul 18 | - ```rust 19 | pub fn flush(&mut self) -> Result<(), OutOfLimit> { 20 | if NEED_ROLLBACK {} 21 | } 22 | state_buffer.flush::() 23 | ``` 24 | - 25 | - ``` 26 | #![deny(unused_crate_dependencies)] 27 | ``` 28 | To detect unused crate when compiling 29 | - https://lazy.codes/posts/awesome-unstable-rust-features/ 30 | - Awesome Unstable Rust Features #read 31 | - 32 | - 33 | - `toy-rpc`: enables `serde_bincode` by default. `bincode` does not support `#[serde(flatten)]`. https://docs.rs/crate/toy-rpc/latest/features 34 | - `bincode` https://github.com/bincode-org/bincode 35 | - does not support `#[serde(flatten)]` and `skip`: https://docs.rs/bincode/2.0.0-alpha.1/bincode/serde/index.html#known-issues 36 | - 37 | - Generate assembly, targeting x86_64, in intel asm syntax: 38 | `rustc -O --crate-type lib --target x86_64 -C "llvm-args=-x86-asm-syntax=intel" --emit asm x.rs` 39 | - 40 | - rust building rollup: 41 | https://forge.rust-lang.org/release/rollups.html 42 | - 43 | - sparse-index: 44 | The feature causes Cargo to access the crates.io index over HTTP, rather than git. It can provide a significant performance improvement, especially if the local copy of the git index is out-of-date or not yet cloned. 45 | `cargo -Z sparse-registry build` 46 | ``` 47 | #.cargo/config.toml 48 | [registries.crates-io] 49 | protocol = "sparse" 50 | ``` 51 | - 52 | - `cargo build --timings` 53 | build time profiling 54 | - `#![deny(clippy::unnecessary_wraps)]` 55 | warn about unnecessary `Result`: should be `T` 56 | - 57 | - cargo watch and build doc 58 | `RUSTDOCFLAGS="-D warnings" cargo watch -x 'doc --all --no-deps'` 59 | - 60 | - implied lifetimes lead to mismatched type error with seemingly identical types in the msg - async closure edition 61 | https://github.com/rust-lang/rust/issues/108114 62 | - Build Postgres Extensions with Rust! 63 | https://github.com/tcdi/pgx 64 | - 65 | - profiling tutorial: 66 | https://www.p99conf.io/2022/08/02/async-rust-in-practice-performance-pitfalls-profiling/ 67 | - 68 | - **cve-rs** 69 | Blazingly 🔥 fast 🚀 memory vulnerabilities, written in 100% safe Rust. 🦀 70 | https://github.com/Speykious/cve-rs -------------------------------------------------------------------------------- /pages/rust-search-engine.md: -------------------------------------------------------------------------------- 1 | - search by function signature: https://roogle.hkmatsumoto.com/ 2 | - chrome-extension: https://rust.extension.sh/ 3 | - 4 | - 5 | - -------------------------------------------------------------------------------- /pages/rust-serialization.md: -------------------------------------------------------------------------------- 1 | - tips: 2 | - [[Rust bincode msgpack 向后兼容性比较]] 3 | - **borsh** #crate 4 | https://github.com/near/borsh-rs 5 | https://borsh.io/ 6 | fixed size elements, much faster, 7 | databend: use borsh to serde aggregation state: https://github.com/datafuselabs/databend/issues/13979 8 | - -------------------------------------------------------------------------------- /pages/rust-unstable-features.md: -------------------------------------------------------------------------------- 1 | - `min_specialization` -------------------------------------------------------------------------------- /pages/serverless.md: -------------------------------------------------------------------------------- 1 | - redis/kafka etc 2 | https://upstash.com/ -------------------------------------------------------------------------------- /pages/tmux.md: -------------------------------------------------------------------------------- 1 | #### cmd: choose-tree 2 | ` s` 3 | display a tree of all window/pane -------------------------------------------------------------------------------- /pages/vercel.md: -------------------------------------------------------------------------------- 1 | - github action to deploy to vercel: 2 | 3 | ``` 4 | - name: Deploy to vercel 5 | env: 6 | VERCEL_ORG_ID: ${{secrets.VERCEL_ORG_ID}} 7 | VERCEL_PROJECT_ID: ${{secrets.VERCEL_PROJECT_ID}} 8 | run: | 9 | npm i -g vercel 10 | vercel --token=${{ secrets.VERCEL_TOKEN }} --prod --scope 11 | ``` 12 | -------------------------------------------------------------------------------- /pages/web-design.md: -------------------------------------------------------------------------------- 1 | - **tailwindcss** 2 | https://tailwindcss.com/ 3 | A utility-first CSS framework packed with classes like flex, pt-4, text-center and rotate-90 that can be composed to build any design, directly in your markup. 4 | - **tailwind colors** 5 | https://tailwindcss.com/docs/customizing-colors 6 | - [[Tailwindcss colors]] 7 | - -------------------------------------------------------------------------------- /pages/web-testing.md: -------------------------------------------------------------------------------- 1 | - re-play `trace file` on line: https://trace.playwright.dev/ 2 | - https://playwright.dev 3 | - 4 | - -------------------------------------------------------------------------------- /pages/z-order.md: -------------------------------------------------------------------------------- 1 | - https://docs.delta.io/latest/optimizations-oss.html#data-skipping 2 | - Z-Ordering is **not idempotent**. Everytime the Z-Ordering is executed it will try to create a new clustering of data in all files (new and existing files that were part of previous Z-Ordering) in a partition. 3 | - Z-Ordering aims to produce evenly-balanced data files with respect to the number of tuples, but not necessarily data size on disk. The two measures are most often correlated, but there can be situations when that is not the case, leading to skew in optimize task times. 4 | 5 | For example, if you ZORDER BY *date* and your most recent records are all much wider (for example longer arrays or string values) than the ones in the past, it is expected that the OPTIMIZE job’s task durations will be skewed, as well as the resulting file sizes. This is, however, only a problem for the OPTIMIZE command itself; it should not have any negative impact on subsequent queries. 6 | - delta.io: 7 | - https://en.wikipedia.org/wiki/Z-order_curve 8 | - 9 | - 10 | - not idempotent: 11 | - -------------------------------------------------------------------------------- /rust-benchmark/.gitignore: -------------------------------------------------------------------------------- 1 | /target 2 | 3 | Cargo.lock 4 | 5 | .DS_Store 6 | -------------------------------------------------------------------------------- /rust-benchmark/Cargo.toml: -------------------------------------------------------------------------------- 1 | [package] 2 | name = "rust-benchmark" 3 | version = "0.1.0" 4 | edition = "2021" 5 | 6 | # See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html 7 | 8 | [dependencies] 9 | 10 | async-trait = "0.1.57" 11 | futures = { version = "0.3.28" } 12 | futures-util = { version = "0.3" } 13 | stream-more = "0.1.3" 14 | 15 | bincode = { version = "1.3.3" } 16 | 17 | rmp-serde = "1.1.1" 18 | serde = { version = "1.0.164", features = ["derive", "rc"] } 19 | serde_json = { version = "1.0.85", default-features = false, features = ["preserve_order"] } 20 | 21 | tokio = { version = "1.12.0", features = ["full"] } 22 | tokio-util = { version = "0.7.1", features = ["full"] } 23 | 24 | ouroboros = { version = "0.18.0" } 25 | bytes = { version = "1.5.0", features = ["serde"] } 26 | 27 | criterion = { version = "0.5.1", features = [] } 28 | 29 | rand = { version = "0.8.5", features = [] } 30 | 31 | [[bench]] 32 | name = "vec-push" 33 | harness = false 34 | -------------------------------------------------------------------------------- /rust-benchmark/rust-toolchain: -------------------------------------------------------------------------------- 1 | nightly-2023-09-01 2 | -------------------------------------------------------------------------------- /rust-playground/.gitignore: -------------------------------------------------------------------------------- 1 | /target 2 | /.idea 3 | 4 | Cargo.lock 5 | 6 | .DS_Store 7 | -------------------------------------------------------------------------------- /rust-playground/Cargo.toml: -------------------------------------------------------------------------------- 1 | cargo-features = ["edition2024"] 2 | 3 | [package] 4 | name = "rust-playground" 5 | version = "0.1.0" 6 | edition = "2021" 7 | #edition = "2024" 8 | 9 | # See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html 10 | 11 | [dependencies] 12 | 13 | anyhow = "1.0.65" 14 | 15 | async-trait = "0.1.57" 16 | futures = { version = "0.3.28" } 17 | futures-util = { version = "0.3" } 18 | futures-async-stream = { version = "0.2.9" } 19 | stream-more = "0.1.3" 20 | 21 | bincode = { version = "1.3.3" } 22 | 23 | rmp-serde = "1.1.1" 24 | serde = { version = "1.0.164", features = ["derive", "rc"] } 25 | serde_json = { version = "1.0.85", default-features = false, features = ["preserve_order"] } 26 | 27 | tokio = { version = "1.12.0", features = ["full"] } 28 | tokio-util = { version = "0.7.1", features = ["full"] } 29 | tonic = { version = "0.11.0", features = ["transport", "codegen", "prost", "tls-roots", "tls"] } 30 | 31 | log = { version = "0.4.21", features = ["serde", "kv_unstable_std"] } 32 | logcall = "0.1.5" 33 | 34 | ouroboros = { version = "0.18.0" } 35 | bytes = { version = "1.5.0", features = ["serde"] } 36 | 37 | criterion = { version = "0.5.1", features = [] } 38 | 39 | rand = { version = "0.8.5", features = [] } 40 | derive_more = "0.99.17" 41 | 42 | 43 | [workspace] 44 | 45 | members = [ 46 | "t-serde-instant" 47 | ] 48 | exclude = [ 49 | "t-im", 50 | ] 51 | 52 | -------------------------------------------------------------------------------- /rust-playground/rust-toolchain: -------------------------------------------------------------------------------- 1 | nightly-2024-05-20 2 | -------------------------------------------------------------------------------- /rust-playground/src/bin/100013-gat-self---a-bounds-break-some-async-blocks-with-impl-trait.rs: -------------------------------------------------------------------------------- 1 | #![feature(generic_associated_types)] 2 | 3 | /// Unexpected higher-ranked lifetime error in GAT usage #100013 4 | /// https://github.com/rust-lang/rust/issues/100013 5 | /// 6 | /// GAT Self: 'a bounds break some async blocks with impl Trait #92096 7 | /// https://github.com/rust-lang/rust/issues/92096 8 | 9 | pub trait FutureIterator { 10 | type Future<'s, 'cx>: Send 11 | where 12 | 's: 'cx; 13 | } 14 | 15 | fn call_2() -> impl Send { 16 | async { 17 | // a generator checked for autotrait impl `Send` 18 | let x = None::>; // a type referencing GAT 19 | async {}.await; // a yield point 20 | } 21 | } 22 | 23 | fn main() {} 24 | -------------------------------------------------------------------------------- /rust-playground/src/bin/async-fn-as-generic-pin-box.rs: -------------------------------------------------------------------------------- 1 | use std::future::Future; 2 | use std::pin::Pin; 3 | 4 | struct Foo 5 | where F: for<'a> Fn(&'a u64) -> Pin + 'a>> 6 | { 7 | doit: F, 8 | } 9 | 10 | impl Foo 11 | where F: for<'a> Fn(&'a u64) -> Pin + 'a>> 12 | { 13 | async fn rock(&self) { 14 | let x = 3u64; 15 | (self.doit)(&x).await; 16 | } 17 | } 18 | 19 | fn sing<'a>(_x: &'a u64) -> Pin + 'a>> { 20 | let f = async move { 21 | println!("{}", _x); 22 | }; 23 | Box::pin(f) 24 | } 25 | 26 | #[tokio::main] 27 | async fn main() { 28 | let f = Foo { doit: sing }; 29 | f.rock().await; 30 | } 31 | -------------------------------------------------------------------------------- /rust-playground/src/bin/async-fn-as-generic.rs: -------------------------------------------------------------------------------- 1 | use std::future::Future; 2 | 3 | struct Foo 4 | where 5 | Fut: Future, 6 | F: for<'a> Fn(&'a u64) -> Fut, 7 | { 8 | doit: F, 9 | } 10 | 11 | impl Foo 12 | where 13 | Fut: Future, 14 | F: for<'a> Fn(&'a u64) -> Fut, 15 | { 16 | async fn rock(&self) { 17 | let x = 3u64; 18 | (self.doit)(&x).await; 19 | } 20 | } 21 | 22 | fn sing<'a>(_x: &'a u64) -> impl Future + 'a { 23 | async move { 24 | println!("{}", _x); 25 | } 26 | } 27 | 28 | #[tokio::main] 29 | async fn main() { 30 | let _f = Foo { 31 | doit: sing, // Fail to compile 32 | }; 33 | 34 | // _f.rock().await; 35 | } 36 | 37 | // error[E0308]: mismatched types 38 | // --> src/bin/try-it.rs:30:14 39 | // | 40 | // 30 | let _f = Foo { 41 | // | ______________^ 42 | // 31 | | doit: sing, // Fail to compile 43 | // 32 | | }; 44 | // | |_____^ one type is more general than the other 45 | // | 46 | // = note: expected trait `for<'a> fn(&'a u64) -> impl Future + 'a {sing} as FnOnce<(&'a u64,)>>` 47 | // found trait `for<'a> fn(&'a u64) -> impl Future + 'a {sing} as FnOnce<(&'a u64,)>>` 48 | // note: the lifetime requirement is introduced here 49 | // --> src/bin/try-it.rs:6:31 50 | // | 51 | // 6 | F: for<'a> Fn(&'a u64) -> Fut, 52 | // | ^^^ 53 | -------------------------------------------------------------------------------- /rust-playground/src/bin/async_read_buf_chunk_size.rs: -------------------------------------------------------------------------------- 1 | use tokio::fs; 2 | use tokio::io::{AsyncReadExt, AsyncWriteExt}; 3 | 4 | #[tokio::main] 5 | async fn main() -> anyhow::Result<()> { 6 | let path = "/Users/drdrxp/foo-data"; 7 | let path_2 = "/Users/drdrxp/foo-data-2"; 8 | let mut f = fs::OpenOptions::new() 9 | // .create_new(true) 10 | // .write(true) 11 | .read(true) 12 | .open(&path) 13 | .await?; 14 | 15 | let mut buf: Vec = Vec::with_capacity(1024 * 1024 * 10); 16 | 17 | while buf.capacity() > buf.len() { 18 | let c = f.read_buf(&mut buf).await?; 19 | if c == 0 { 20 | break; 21 | } 22 | } 23 | 24 | let mut f = fs::OpenOptions::new() 25 | .create_new(true) 26 | .write(true) 27 | .read(true) 28 | .open(&path_2) 29 | .await?; 30 | 31 | f.write_all(&buf).await?; 32 | 33 | println!("n={}", buf.len()); 34 | Ok(()) 35 | } 36 | -------------------------------------------------------------------------------- /rust-playground/src/bin/borrow-of-moved-reborrow.rs: -------------------------------------------------------------------------------- 1 | struct Foo; 2 | 3 | // error[E0382]: borrow of moved value: `v` 4 | // | 5 | // | fn borrow_of_moved_error(v: &mut Foo) { 6 | // | - move occurs because `v` has type `&mut Foo`, 7 | // | which does not implement the `Copy` trait 8 | // | generic_write(v); 9 | // | - value moved here 10 | // | write(v); 11 | // | ^ value borrowed here after move 12 | fn borrow_of_moved_error(v: &mut Foo) { 13 | generic_write(v); 14 | write(v); 15 | } 16 | 17 | fn solution(v: &mut Foo) { 18 | // Solution: manually re-borrow with `&mut *v`. 19 | // Refer to: https://github.com/rust-lang/rust/issues/62112 20 | // 21 | // Forcing the generic type is also a solution: 22 | // `Self::generic_write::<&mut Foo>(v);` 23 | generic_write(&mut *v); 24 | write(v); 25 | } 26 | 27 | fn generic_write(_v: V) {} 28 | fn write(_v: &mut Foo) {} 29 | 30 | fn main() {} 31 | -------------------------------------------------------------------------------- /rust-playground/src/bin/box-stream-to-impl-void-error-2.rs: -------------------------------------------------------------------------------- 1 | //! When passing a BoxStream<'static> to a function expecting `impl Void`, 2 | //! the function does not compile. 3 | //! 4 | //! Although this issue requries many conditions: 5 | //! - a non-Pin-Box stream is ok. 6 | //! - replace `impl Void` with impl Stream + Send + 'static is ok. 7 | //! - without sleep() is ok. 8 | //! - without request.void() is ok. 9 | //! - write it in `async fn` form is ok. 10 | 11 | use futures::stream; 12 | use futures::Stream; 13 | use std::future::Future; 14 | use std::pin::Pin; 15 | use tokio::time::Duration; 16 | 17 | async fn func_ok() -> () { 18 | let strm = stream::iter(vec![]); 19 | let strm: Pin + Send + 'static>> = Box::pin(strm); 20 | 21 | stream_snapshot(strm).await; 22 | } 23 | 24 | fn func_ok2() -> impl Future + Send { 25 | let strm = stream::iter(vec![]); 26 | let strm: Pin + Send + 'static>> = Box::pin(strm); 27 | 28 | stream_snapshot(strm) 29 | } 30 | 31 | // This emit higher rank lifetime error: 32 | fn func_not_compile() -> impl Future { 33 | let strm = stream::iter(vec![]); 34 | let strm: Pin + Send + 'static>> = Box::pin(strm); 35 | 36 | async move { 37 | stream_snapshot(strm).await; 38 | } 39 | } 40 | 41 | pub async fn stream_snapshot(request: impl Void) -> () { 42 | let _req = request.void(); 43 | tokio::time::sleep(Duration::from_secs(1)).await; 44 | } 45 | 46 | pub trait Void { 47 | type Stream: Stream + Send + 'static; 48 | fn void(self) -> Self::Stream; 49 | } 50 | 51 | impl Void for Pin + Send + 'static>> { 52 | type Stream = Self; 53 | 54 | fn void(self) -> Self::Stream { 55 | self 56 | } 57 | } 58 | 59 | fn main() {} 60 | -------------------------------------------------------------------------------- /rust-playground/src/bin/box-stream-to-impl-void-lifetime-error.rs: -------------------------------------------------------------------------------- 1 | //! When passing a BoxStream<'static> to a function expecting `impl Void`, 2 | //! the function does not compile. 3 | //! 4 | //! Although this issue requries many conditions: 5 | //! - a non-Pin-Box stream is ok. 6 | //! - replace `impl Void` with impl Stream + Send + 'static is ok. 7 | //! - without sleep() is ok. 8 | //! - without request.void() is ok. 9 | //! - write it in `async fn` form is ok. 10 | 11 | use futures::stream; 12 | use futures::Stream; 13 | use std::future::Future; 14 | use std::pin::Pin; 15 | use tokio::time::Duration; 16 | 17 | async fn func_ok() -> () { 18 | let strm = stream::iter(vec![]); 19 | let strm: Pin + Send + 'static>> = Box::pin(strm); 20 | 21 | stream_snapshot(strm).await; 22 | } 23 | 24 | fn func_ok2() -> impl Future + Send { 25 | let strm = stream::iter(vec![]); 26 | let strm: Pin + Send + 'static>> = Box::pin(strm); 27 | 28 | stream_snapshot(strm) 29 | } 30 | 31 | fn func_ok3() -> impl Future + Send { 32 | let strm: stream::Iter> = stream::iter(vec![]); 33 | 34 | async move { 35 | stream_snapshot(strm).await; 36 | } 37 | } 38 | 39 | // // This emit higher rank lifetime error: 40 | // fn func_not_compile() -> impl Future + Send { 41 | // let strm = stream::iter(vec![]); 42 | // let strm: Pin + Send + 'static>> = Box::pin(strm); 43 | // 44 | // async move { 45 | // stream_snapshot(strm).await; 46 | // } 47 | // } 48 | 49 | // This emit lifetime error: 50 | // error[E0477]: the type `Pin + std::marker::Send>>` does not fulfill the required lifetime 51 | // trait Net { 52 | // fn send_stream(&self) -> impl Future + Send; 53 | // } 54 | // struct Foo; 55 | // impl Net for Foo { 56 | // async fn send_stream(&self) -> () { 57 | // let strm = stream::iter(vec![]); 58 | // let strm: Pin + Send + 'static>> = Box::pin(strm); 59 | // stream_snapshot(strm).await; 60 | // } 61 | // } 62 | 63 | pub async fn stream_snapshot(request: impl Void) -> () { 64 | let _req = request.void(); 65 | tokio::time::sleep(Duration::from_secs(1)).await; 66 | } 67 | 68 | pub trait Void { 69 | type Stream: Stream + Send + 'static; 70 | fn void(self) -> Self::Stream; 71 | } 72 | 73 | impl Void for T 74 | where 75 | T: Stream + Send + 'static, 76 | { 77 | type Stream = T; 78 | 79 | fn void(self) -> T { 80 | self 81 | } 82 | } 83 | 84 | fn main() {} 85 | -------------------------------------------------------------------------------- /rust-playground/src/bin/box-trait-object-fat-pointer.rs: -------------------------------------------------------------------------------- 1 | use std::any::Any; 2 | 3 | trait MyTrait { 4 | fn echo(&self); 5 | } 6 | 7 | struct MyStruct { 8 | a: u64, 9 | } 10 | 11 | impl Drop for MyStruct { 12 | fn drop(&mut self) { 13 | println!("dropped: {}", self.a) 14 | } 15 | } 16 | 17 | impl MyTrait for MyStruct { 18 | fn echo(&self) { 19 | println!("MyStruct: {}", self.a) 20 | } 21 | } 22 | 23 | /// A wrapper of a `ExternalRequestFn` trait object that erases type parameters and make it `Send`. 24 | /// 25 | /// This wrapper erases type parameters so that the channel for sending it does not need to contain the type parameters. 26 | /// Only the sending end and the receiving end need to agree on the type parameters. 27 | /// 28 | /// Internally, it stores the `ExternalRequestFn` trait object's data pointer in a `Box`, 29 | /// so that the `Drop::drop()` will be called when the wrapper is dropped. 30 | /// And it stores the vtable pointer in another `usize` to make sure it is `Send`. 31 | struct ExternalRequest { 32 | /// The data pointer. 33 | /// 34 | /// Wrap it in a `Box` to make sure it is dropped when `Boo` is dropped. 35 | data: Box, 36 | 37 | /// The vtable pointer. 38 | /// 39 | /// Stored in `usize` to make sure it is `Send`. 40 | vtable: usize, 41 | } 42 | 43 | impl ExternalRequest { 44 | fn new(v: V) -> Self { 45 | let raw: *const dyn MyTrait = &v; 46 | let (_data, vtable): (*const (), *const ()) = unsafe { std::mem::transmute(raw) }; 47 | Self { 48 | data: Box::new(v), 49 | vtable: vtable as usize, 50 | } 51 | } 52 | 53 | fn unpack(self) -> Box { 54 | let raw: *const dyn Any = Box::into_raw(self.data); 55 | let (data, mut vtable): (*const (), *const ()) = unsafe { std::mem::transmute(raw) }; 56 | vtable = self.vtable as *const (); 57 | 58 | let raw: *mut dyn MyTrait = unsafe { std::mem::transmute((data, vtable)) }; 59 | 60 | unsafe { Box::from_raw(raw) } 61 | } 62 | } 63 | 64 | fn assert_send(_v: &T) {} 65 | 66 | fn main() { 67 | { 68 | let x = MyStruct { a: 5 }; 69 | let b = ExternalRequest::new(x); 70 | 71 | assert_send(&b); 72 | 73 | let y = b.unpack(); 74 | y.echo(); 75 | } 76 | 77 | let x = MyStruct { a: 1 }; 78 | 79 | { 80 | let raw: *const dyn MyTrait = &x; 81 | let (data_1, vtable_1): (*const (), *const ()) = unsafe { std::mem::transmute(raw) }; 82 | println!("Data pointer: {:?}", data_1); 83 | println!("Vtable pointer: {:?}", vtable_1); 84 | } 85 | 86 | { 87 | let raw: *const dyn Any = &x; 88 | let (data_1, vtable_1): (*const (), *const ()) = unsafe { std::mem::transmute(raw) }; 89 | println!("Data pointer: {:?}", data_1); 90 | println!("Vtable pointer: {:?}", vtable_1); 91 | } 92 | 93 | { 94 | let b1: Box = Box::new(MyStruct { a: 4 }); 95 | 96 | let raw1: *const dyn Any = Box::into_raw(b1); 97 | let (data_1, vtable_1): (*const (), *const ()) = unsafe { std::mem::transmute(raw1) }; 98 | 99 | println!("Data pointer: {:?}", data_1); 100 | println!("Vtable pointer: {:?}", vtable_1); 101 | 102 | let _ = unsafe { Box::from_raw(raw1 as *mut dyn Any) }; 103 | } 104 | 105 | let b1: Box = Box::new(MyStruct { a: 3 }); 106 | 107 | let raw1: *const dyn MyTrait = Box::into_raw(b1); 108 | let (data_1, vtable_1): (*const (), *const ()) = unsafe { std::mem::transmute(raw1) }; 109 | 110 | println!("Data pointer: {:?}", data_1); 111 | println!("Vtable pointer: {:?}", vtable_1); 112 | 113 | let _ = unsafe { Box::from_raw(raw1 as *mut dyn MyTrait) }; 114 | } 115 | -------------------------------------------------------------------------------- /rust-playground/src/bin/bsearch-branchless.rs: -------------------------------------------------------------------------------- 1 | fn bsearch(elts: &[T], v: &T) -> usize { 2 | let mut lr = [0, elts.len()]; 3 | 4 | while lr[0] + 1 < lr[1] { 5 | let mid = (lr[0] + lr[1]) / 2; 6 | lr[(v < &elts[mid]) as usize] = mid; 7 | } 8 | lr[0] 9 | } 10 | 11 | fn main() { 12 | let a: Vec = vec![1, 2, 5, 7, 8]; 13 | 14 | for v in [0, 1, 2, 3, 4, 5, 6, 7, 8, 9] { 15 | let index = bsearch(&a, &v); 16 | println!("bsearch({:?}, {}) -> {}", a, v, index); 17 | } 18 | } 19 | -------------------------------------------------------------------------------- /rust-playground/src/bin/bug-send-higher-ranked-lifetime.rs: -------------------------------------------------------------------------------- 1 | #![feature(type_alias_impl_trait)] 2 | 3 | //! Build a minimized reproducible example for: 4 | //! 5 | //! https://github.com/rust-lang/rust/issues/100013 6 | //! https://github.com/rust-lang/rust/issues/114046 7 | //! https://github.com/rust-lang/rust/issues/110338 8 | 9 | use std::future::Future; 10 | 11 | pub fn assert_send(v: T) -> T { 12 | v 13 | } 14 | 15 | pub struct Level {} 16 | pub struct Level2 {} 17 | 18 | pub trait MapApiRO: Send + Sync { 19 | type GetFut<'f>: Future 20 | where 21 | Self: 'f; 22 | 23 | fn get<'f>(self) -> Self::GetFut<'f>; 24 | } 25 | 26 | impl<'d> MapApiRO for &'d Level { 27 | type GetFut<'f> = impl Future + 'f where Self: 'f; 28 | 29 | fn get<'f>(self) -> Self::GetFut<'f> 30 | where 31 | Self: 'f, 32 | { 33 | async move { () } 34 | } 35 | } 36 | 37 | impl<'ro_d> MapApiRO for &'ro_d Level2 38 | where 39 | for<'e> &'e Level: MapApiRO, 40 | { 41 | type GetFut<'f> = impl Future + 'f where Self: 'f; 42 | 43 | fn get<'f>(self) -> Self::GetFut<'f> 44 | where 45 | Self: 'f, 46 | { 47 | async move { 48 | let l = Level {}; 49 | l.get().await 50 | } 51 | } 52 | } 53 | 54 | #[tokio::main] 55 | async fn main() { 56 | let l = Level {}; 57 | let fu = l.get(); 58 | let _ = assert_send(fu); 59 | 60 | // error: implementation of `MapApiRO` is not general enough 61 | // --> src/bin/map-api-send-higher-ranked-lifetime.rs:60:13 62 | // | 63 | // 60 | let _ = assert_send(fu); 64 | // | ^^^^^^^^^^^^^^^ implementation of `MapApiRO` is not general enough 65 | // | 66 | // = note: `MapApiRO` would have to be implemented for the type `&'0 Level`, for any lifetime `'0`... 67 | // = note: ...but `MapApiRO` is actually implemented for the type `&'1 Level`, for some specific lifetime `'1` 68 | let static_levels = Level2 {}; 69 | let fu = static_levels.get(); 70 | let _ = assert_send(fu); 71 | } 72 | -------------------------------------------------------------------------------- /rust-playground/src/bin/cell-test.rs: -------------------------------------------------------------------------------- 1 | use std::cell::Cell; 2 | 3 | struct Bar { 4 | i: u64, 5 | j: u64, 6 | } 7 | 8 | struct Foo { 9 | a: Cell, 10 | } 11 | 12 | fn doit(x: &Foo) { 13 | let mut a = x.a.get_mut(); 14 | a.i = 3; 15 | } 16 | 17 | fn main() { 18 | let x = Foo { 19 | a: Cell::new(Bar { i: 1, j: 2 }), 20 | }; 21 | } 22 | -------------------------------------------------------------------------------- /rust-playground/src/bin/cfg-test.rs: -------------------------------------------------------------------------------- 1 | fn main() { 2 | 3 | } 4 | -------------------------------------------------------------------------------- /rust-playground/src/bin/compatible-error.rs: -------------------------------------------------------------------------------- 1 | /// Compatible layer to receive different types of errors from meta-service. 2 | /// 3 | /// It allows the server side to switch to return a smaller error type, e.g., from KVAppError to MetaAPIError. 4 | /// 5 | /// Currently: 6 | /// - Meta service kv_api returns KVAppError, while the client only consume the MetaApiError variants 7 | #[derive(thiserror::Error, serde::Serialize, serde::Deserialize, Debug, Clone, PartialEq, Eq)] 8 | #[serde(untagged)] 9 | pub enum Compatible 10 | where 11 | Outer: From, 12 | Outer: TryInto, 13 | { 14 | Outer(Outer), 15 | Inner(Inner), 16 | } 17 | 18 | impl Compatible 19 | where 20 | Outer: From, 21 | Outer: TryInto, 22 | { 23 | pub fn into_inner(self) -> Inner 24 | where Inner: From<>::Error> { 25 | match self { 26 | Compatible::Outer(o) => { 27 | let i: Inner = o.try_into().unwrap_or_else(|e| Inner::from(e)); 28 | i 29 | } 30 | Compatible::Inner(i) => i, 31 | } 32 | } 33 | } 34 | 35 | #[cfg(test)] 36 | mod tests { 37 | use databend_common_meta_types::ForwardToLeader; 38 | use databend_common_meta_types::MembershipNode; 39 | use databend_common_meta_types::MetaAPIError; 40 | use databend_common_meta_types::MetaError; 41 | 42 | use crate::compat_errors::Compatible; 43 | use crate::kv_app_error::KVAppError; 44 | 45 | #[test] 46 | fn test_read_api_err_from_api_err() -> anyhow::Result<()> { 47 | let me = MetaAPIError::ForwardToLeader(ForwardToLeader { 48 | leader_id: Some(1), 49 | leader_node: Some(MembershipNode {}), 50 | }); 51 | let s = serde_json::to_string(&me)?; 52 | 53 | let ge: Compatible = serde_json::from_str(&s)?; 54 | 55 | if let MetaAPIError::ForwardToLeader(f) = ge.clone().into_inner() { 56 | assert_eq!(Some(1), f.leader_id); 57 | } else { 58 | unreachable!("expect ForwardToLeader but: {:?}", ge); 59 | } 60 | 61 | Ok(()) 62 | } 63 | 64 | #[test] 65 | fn test_read_api_err_from_kv_app_err() -> anyhow::Result<()> { 66 | let me = KVAppError::MetaError(MetaError::APIError(MetaAPIError::ForwardToLeader( 67 | ForwardToLeader { 68 | leader_id: Some(1), 69 | leader_node: Some(MembershipNode {}), 70 | }, 71 | ))); 72 | let s = serde_json::to_string(&me)?; 73 | 74 | let ge: Compatible = serde_json::from_str(&s)?; 75 | 76 | if let MetaAPIError::ForwardToLeader(f) = ge.clone().into_inner() { 77 | assert_eq!(Some(1), f.leader_id); 78 | } else { 79 | unreachable!("expect ForwardToLeader but: {:?}", ge); 80 | } 81 | 82 | Ok(()) 83 | } 84 | } 85 | -------------------------------------------------------------------------------- /rust-playground/src/bin/either.rs: -------------------------------------------------------------------------------- 1 | use std::any::{Any, TypeId}; 2 | use std::mem::ManuallyDrop; 3 | use std::ptr::read_unaligned; 4 | 5 | unsafe fn transmute_unchecked(t: T) -> U { 6 | let uninit = ManuallyDrop::new(t); 7 | read_unaligned(&*uninit as *const _ as *const U) 8 | } 9 | 10 | enum Impossible {} 11 | 12 | enum OneOf2 { 13 | V1(T1), 14 | V2(T2), 15 | } 16 | 17 | impl OneOf2 18 | where 19 | T1: Any + 'static, 20 | T2: Any + 'static, 21 | { 22 | fn new(t: T) -> Self 23 | where 24 | T: Any + 'static, 25 | { 26 | let tid = TypeId::of::(); 27 | 28 | if tid == TypeId::of::() { 29 | Self::V1(unsafe { transmute_unchecked(t) }) 30 | } else if tid == TypeId::of::() { 31 | Self::V2(unsafe { transmute_unchecked(t) }) 32 | } else { 33 | unreachable!() 34 | } 35 | } 36 | 37 | fn get(&self) -> Option<&T> 38 | where 39 | T: 'static, 40 | { 41 | let d = match self { 42 | Self::V1(l) => l as &dyn Any, 43 | Self::V2(r) => r as &dyn Any, 44 | }; 45 | d.downcast_ref::() 46 | } 47 | } 48 | 49 | enum OneOf3 { 50 | V1(T1), 51 | V2(T2), 52 | V3(T3), 53 | } 54 | 55 | impl OneOf3 56 | where 57 | T1: Any + 'static, 58 | T2: Any + 'static, 59 | T3: Any + 'static, 60 | { 61 | fn new(t: T) -> Self 62 | where 63 | T: Any + 'static, 64 | { 65 | let tid = TypeId::of::(); 66 | 67 | if tid == TypeId::of::() { 68 | Self::V1(unsafe { transmute_unchecked(t) }) 69 | } else if tid == TypeId::of::() { 70 | Self::V2(unsafe { transmute_unchecked(t) }) 71 | } else if tid == TypeId::of::() { 72 | Self::V3(unsafe { transmute_unchecked(t) }) 73 | } else { 74 | unreachable!() 75 | } 76 | } 77 | 78 | fn get(&self) -> Option<&T> 79 | where 80 | T: 'static, 81 | { 82 | let d = match self { 83 | Self::V1(l) => l as &dyn Any, 84 | Self::V2(r) => r as &dyn Any, 85 | Self::V3(c) => c as &dyn Any, 86 | }; 87 | d.downcast_ref::() 88 | } 89 | } 90 | 91 | impl From> for OneOf3 { 92 | fn from(value: OneOf2) -> Self { 93 | match value { 94 | OneOf2::V1(v) => OneOf3::V1(v), 95 | OneOf2::V2(v) => OneOf3::V2(v), 96 | } 97 | } 98 | } 99 | 100 | fn main() { 101 | let e: OneOf3 = OneOf3::new(1u8); 102 | println!("a: {:?}", e.get::()); 103 | println!("b: {:?}", e.get::()); 104 | println!("c: {:?}", e.get::()); 105 | 106 | let e: OneOf3 = OneOf3::new(2u16); 107 | println!("a: {:?}", e.get::()); 108 | println!("b: {:?}", e.get::()); 109 | println!("c: {:?}", e.get::()); 110 | 111 | let e: OneOf3 = OneOf3::new(3u32); 112 | println!("a: {:?}", e.get::()); 113 | println!("b: {:?}", e.get::()); 114 | println!("c: {:?}", e.get::()); 115 | 116 | let o2: OneOf2 = OneOf2::new(1u8); 117 | let o3 = OneOf3::::from(o2); 118 | println!("a: {:?}", o3.get::()); 119 | } 120 | 121 | type APIError = OneOf3; 122 | 123 | fn install_snapshot() -> Result> {} 124 | -------------------------------------------------------------------------------- /rust-playground/src/bin/enum-size.rs: -------------------------------------------------------------------------------- 1 | use std::mem::size_of; 2 | use std::sync::Arc; 3 | 4 | trait Trait {} 5 | 6 | // size: 8 7 | // Arc 8 | // size: 16 9 | // Arc 10 | 11 | // size: 8; without tag 12 | enum Blank_Arc { 13 | Blank, 14 | Arc(Arc), 15 | } 16 | 17 | // size: 16; without tag 18 | enum Blank_ArcDyn { 19 | Blank, 20 | ArcDyn(Arc), 21 | } 22 | 23 | // size: 16; with tag 24 | enum Arc_Arc { 25 | Arc1(Arc), 26 | Arc2(Arc), 27 | } 28 | 29 | // size: 16; without tag 30 | enum Arc_ArcDyn { 31 | Arc(Arc), 32 | ArcDyn(Arc), 33 | } 34 | 35 | // size: 24; with tag 36 | enum ArcDyn_ArcDyn { 37 | ArcDyn1(Arc), 38 | ArcDyn2(Arc), 39 | } 40 | 41 | // size: 24; with tag 42 | enum Blank_Arc_ArcDyn { 43 | Blank, 44 | Arc(Arc), 45 | ArcDyn(Arc), 46 | } 47 | 48 | // 8 bytes 49 | struct WithNiche { 50 | fill1: u32, 51 | fill2: u16, 52 | fill3: u8, 53 | niche: bool, 54 | } 55 | 56 | // 8 bytes, using the value 2-255 in the last byte in `WithNiche` as tag. 57 | enum Enum { 58 | NicheContainingVariant(WithNiche), 59 | B4bytes(u32), 60 | C4bytes(f32), 61 | D6bytes([u16;3]), 62 | } 63 | 64 | fn main() { 65 | println!("Arc : {}", size_of::>()); 66 | println!("Arc : {}", size_of::>()); 67 | 68 | println!("enum{{Blank, Arc}} : {}", size_of::()); 69 | println!("enum{{Blank, Arc}} : {}", size_of::()); 70 | println!("enum{{Arc, Arc}} : {}", size_of::()); 71 | println!("enum{{Arc, Arc}} : {}", size_of::()); 72 | println!("enum{{Arc, Arc}} : {}", size_of::()); 73 | println!("enum{{Blank, Arc, Arc}} : {}", size_of::()); 74 | 75 | println!("WithNiche : {}", size_of::()); 76 | println!("Enum : {}", size_of::()); 77 | 78 | } 79 | -------------------------------------------------------------------------------- /rust-playground/src/bin/framed-async-read-to-stream.rs: -------------------------------------------------------------------------------- 1 | use futures_util::StreamExt; 2 | use tokio_util::codec::{FramedRead, LinesCodec}; 3 | 4 | #[tokio::main] 5 | async fn main() { 6 | // Convert AsyncRead into a line based FramedRead 7 | let mut framed = FramedRead::new(tokio::io::stdin(), LinesCodec::new()); 8 | 9 | while let Some(line) = framed.next().await { 10 | println!("{:?}", line); 11 | } 12 | } 13 | -------------------------------------------------------------------------------- /rust-playground/src/bin/future-now-or-never.rs: -------------------------------------------------------------------------------- 1 | use futures::TryStream; 2 | use futures_util::FutureExt; 3 | use std::fmt::Debug; 4 | use std::io; 5 | use std::ops::RangeBounds; 6 | 7 | fn main() { 8 | use futures::{future::pending, future::ready}; 9 | let mut future_ready = ready("foobar"); 10 | let mut future_pending = pending::<&'static str>(); 11 | 12 | assert_eq!((&mut future_ready).now_or_never(), Some("foobar")); 13 | assert_eq!((&mut future_pending).now_or_never(), None); 14 | assert_eq!((&mut future_pending).now_or_never(), None); 15 | } 16 | 17 | trait OptionalSend {} 18 | trait OptionalSync {} 19 | trait RaftTypeConfig { 20 | type NodeId; 21 | type Entry; 22 | } 23 | 24 | pub trait RaftLogReader: OptionalSend + OptionalSync + 'static + Send 25 | where 26 | C: RaftTypeConfig, 27 | { 28 | fn entries_stream( 29 | &mut self, 30 | start: u64, 31 | ) -> impl std::future::Future< 32 | Output = Result, io::Error>, 33 | > + Send { 34 | async move { Ok(futures::stream::iter(vec![])) } 35 | } 36 | } 37 | -------------------------------------------------------------------------------- /rust-playground/src/bin/futures-async-stream--try_stream.rs: -------------------------------------------------------------------------------- 1 | #![feature(generators)] 2 | 3 | use futures::stream::Stream; 4 | use futures_async_stream::try_stream; 5 | use futures_util::TryStreamExt; 6 | use std::collections::BTreeMap; 7 | use std::num::ParseIntError; 8 | 9 | #[try_stream(boxed, ok = i32, error = ParseIntError)] 10 | async fn foo(stream: impl Stream + Send + 'static) { 11 | #[for_await] 12 | for x in stream { 13 | yield x.parse()?; 14 | } 15 | } 16 | 17 | #[tokio::main] 18 | async fn main() -> anyhow::Result<()> { 19 | let mut s = foo(futures::stream::iter(["1".to_string()])); 20 | while let Some(x) = s.try_next().await? { 21 | println!("{}", x); 22 | } 23 | 24 | let x: BTreeMap = BTreeMap::new(); 25 | 26 | let v = x.range(""..); 27 | 28 | Ok(()) 29 | } 30 | -------------------------------------------------------------------------------- /rust-playground/src/bin/gat-future-iskyzh.rs: -------------------------------------------------------------------------------- 1 | #![feature(type_alias_impl_trait)] 2 | 3 | use std::io::Write; 4 | 5 | use bytes::Bytes; 6 | use std::future::Future; 7 | 8 | pub trait KvIterator { 9 | type NextFuture<'a>: Future> 10 | where 11 | Self: 'a; 12 | 13 | /// Get the next item from the iterator. 14 | fn next<'x>(&'x mut self) -> Self::NextFuture<'_>; 15 | } 16 | 17 | pub struct TestIterator { 18 | idx: usize, 19 | to_idx: usize, 20 | key: Vec, 21 | value: Vec, 22 | } 23 | 24 | impl TestIterator { 25 | pub fn new(from_idx: usize, to_idx: usize) -> Self { 26 | Self { 27 | idx: from_idx, 28 | to_idx, 29 | key: Vec::new(), 30 | value: Vec::new(), 31 | } 32 | } 33 | } 34 | impl KvIterator for TestIterator { 35 | type NextFuture<'a> = impl Future> where Self: 'a; 36 | 37 | fn next<'x>(&'x mut self) -> Self::NextFuture<'_> { 38 | async move { 39 | if self.idx >= self.to_idx { 40 | return None; 41 | } 42 | 43 | // Zero-allocation key value manipulation 44 | 45 | self.key.clear(); 46 | write!(&mut self.key, "key_{:05}", self.idx).unwrap(); 47 | 48 | self.value.clear(); 49 | write!(&mut self.value, "value_{:05}", self.idx).unwrap(); 50 | 51 | self.idx += 1; 52 | Some((&self.key[..], &self.value[..])) 53 | } 54 | } 55 | } 56 | 57 | pub struct ConcatIterator { 58 | iters: Vec, 59 | current_idx: usize, 60 | } 61 | 62 | impl ConcatIterator { 63 | pub fn new(iters: Vec) -> Self { 64 | Self { 65 | iters, 66 | current_idx: 0, 67 | } 68 | } 69 | } 70 | 71 | impl KvIterator for ConcatIterator { 72 | type NextFuture<'a> = impl Future> where Self: 'a; 73 | 74 | fn next<'x>(&'x mut self) -> Self::NextFuture<'_> { 75 | let l = self.iters.len(); 76 | 77 | async move { 78 | loop { 79 | if self.current_idx >= l { 80 | return None; 81 | } 82 | 83 | let iter = &mut self.iters[self.current_idx]; 84 | 85 | let res = iter.next().await; 86 | 87 | if res.is_some() { 88 | return res; 89 | } 90 | 91 | self.current_idx += 1; 92 | } 93 | } 94 | } 95 | } 96 | 97 | #[tokio::main] 98 | async fn main() { 99 | let mut iter = TestIterator::new(0, 10); 100 | while let Some((key, value)) = iter.next().await { 101 | println!( 102 | "{:?} {:?}", 103 | Bytes::copy_from_slice(key), 104 | Bytes::copy_from_slice(value) 105 | ); 106 | } 107 | } 108 | -------------------------------------------------------------------------------- /rust-playground/src/bin/gat-future-multi-lifetime.rs: -------------------------------------------------------------------------------- 1 | #![feature(type_alias_impl_trait)] 2 | 3 | use futures::executor::block_on; 4 | use std::borrow::Borrow; 5 | use std::future::Future; 6 | 7 | #[derive(Debug, Clone, PartialEq, Eq, PartialOrd, Ord, Hash)] 8 | struct Val(u64); 9 | 10 | trait MapApiRO<'d, K>: Send + Sync { 11 | type GetFut<'f, 'g>: Future 12 | where 13 | Self: 'f, 14 | Self: 'g; 15 | 16 | fn get<'f, 'g>(self, key: &'f u64, v: &'g u64) -> Self::GetFut<'f, 'g>; 17 | } 18 | 19 | struct Foo; 20 | 21 | impl<'d, K> MapApiRO<'d, K> for Foo { 22 | type GetFut<'f, 'g> = impl Future + 'f + 'g 23 | where 24 | Self: 'f, 25 | Self: 'g 26 | ; 27 | 28 | fn get<'f, 'g>(self, key: &'f u64, v: &'g u64) -> Self::GetFut<'f, 'g> { 29 | async move { 30 | // 31 | 1 32 | } 33 | } 34 | } 35 | 36 | fn main() { 37 | let mut foo = Foo; 38 | 39 | let k = 1; 40 | let v = 2; 41 | 42 | let fut = block_on(>::get(foo, &k, &v)); 43 | 44 | println!("{:?}", fut); 45 | } 46 | -------------------------------------------------------------------------------- /rust-playground/src/bin/get-stack-pos-unsafe.rs: -------------------------------------------------------------------------------- 1 | // https://github.com/SkyFan2002/databend/commit/2e4d28a7714b5f71294eefd463c4840ab7b9d038 2 | 3 | // thread_local! { 4 | // static RSP: isize = get_rsp(); 5 | // } 6 | 7 | // pub fn get_rsp() -> isize { 8 | // let rsp: isize; 9 | // unsafe { 10 | // core::arch::asm!("mov {}, rsp", out(reg) rsp); 11 | // } 12 | // rsp 13 | // } 14 | // pub fn check() { 15 | // let rsp = get_rsp(); 16 | // 17 | // let base = RSP.with(|&v| v); 18 | // 19 | // let stack_size = base - rsp; 20 | // 21 | // let m = stack_size / 1024 / 1024; 22 | // 23 | // let k = (stack_size - m * 1024 * 1024) / 1024; 24 | // 25 | // let b = stack_size - m * 1024 * 1024 - k * 1024; 26 | // 27 | // println!("stack size: {}M {}K {}B", m, k, b); 28 | // } 29 | -------------------------------------------------------------------------------- /rust-playground/src/bin/get_type_macro.rs: -------------------------------------------------------------------------------- 1 | #![feature(core_intrinsics)] // Needed for `type_id` 2 | 3 | use std::any::Any; 4 | macro_rules! get_type { 5 | ($trait_type:ty, $value:expr) => {{ 6 | let trait_object_ref: &$trait_type = &$value; 7 | 8 | let type_id = std::intrinsics::type_id::<$trait_type>(); 9 | 10 | let vtable = { 11 | let fat_ptr: *const $trait_type = trait_object_ref; 12 | let (_data, vtable): (*const (), *const ()) = unsafe { std::mem::transmute(fat_ptr) }; 13 | vtable as usize 14 | }; 15 | 16 | (type_id, vtable) 17 | }}; 18 | } 19 | 20 | // Example usage 21 | trait ExampleTrait { 22 | fn example_method(&self); 23 | } 24 | 25 | impl ExampleTrait for String { 26 | fn example_method(&self) { 27 | // Implementation 28 | } 29 | } 30 | 31 | fn main() { 32 | { 33 | let my_string = "Hello, World!".to_string(); 34 | 35 | // let (type_id, vtable) = get_type!(dyn ExampleTrait, my_string); 36 | // println!("TypeId: {:?}", type_id); 37 | // println!("VTable: {:?}", vtable); 38 | 39 | let t: Box = Box::new(my_string); 40 | let u = t.downcast::(); 41 | } 42 | { 43 | let my_string = "Hello, World!".to_string(); 44 | let boxed: Box = Box::new(my_string); 45 | let box2: Box = Box::new(boxed); 46 | let _u: Box> = box2.downcast::>().unwrap(); 47 | } 48 | } 49 | -------------------------------------------------------------------------------- /rust-playground/src/bin/gg.rs: -------------------------------------------------------------------------------- 1 | trait Quorum { 2 | fn ids<'s>(&'s self) -> impl Iterator + 'static; 3 | } 4 | 5 | struct Example { 6 | data: Vec, 7 | } 8 | 9 | impl Quorum for Example { 10 | fn ids<'s>(&'s self) -> impl Iterator + 'static { 11 | self.data.clone().into_iter() 12 | } 13 | } 14 | fn main() {} 15 | -------------------------------------------------------------------------------- /rust-playground/src/bin/impl-by-trait.rs: -------------------------------------------------------------------------------- 1 | //! Try to implement differently for a method if the struct implements a trait. 2 | //! 3 | //! Using specialization it can be done. 4 | 5 | #![feature(specialization)] 6 | 7 | trait Trait {} 8 | 9 | trait Doit { 10 | fn doit() -> u64 { 11 | 0 12 | } 13 | } 14 | 15 | #[derive()] 16 | struct Foo { 17 | _p: std::marker::PhantomData, 18 | } 19 | 20 | impl Doit for Foo { 21 | default fn doit() -> u64 { 22 | 3 23 | } 24 | } 25 | 26 | impl Doit for Foo 27 | where 28 | T: Trait, 29 | { 30 | fn doit() -> u64 { 31 | 4 32 | } 33 | } 34 | 35 | impl Trait for u32 {} 36 | 37 | fn main() { 38 | println!("{}", Foo::::doit()); 39 | println!("{}", Foo::::doit()); 40 | } 41 | -------------------------------------------------------------------------------- /rust-playground/src/bin/impl-trait-for-option-generic-conflict.rs: -------------------------------------------------------------------------------- 1 | pub trait Str { 2 | fn to_str(&self) -> String; 3 | } 4 | 5 | impl Str for u64 { 6 | fn to_str(&self) -> String { 7 | format!("{}", self) 8 | } 9 | } 10 | 11 | impl Str for Option { 12 | fn to_str(&self) -> String { 13 | self.as_ref().to_str() 14 | } 15 | } 16 | 17 | impl Str for Option<&V> { 18 | fn to_str(&self) -> String { 19 | self.map(|x| x.to_str()).unwrap_or("-".to_string()) 20 | } 21 | } 22 | 23 | fn main() { 24 | println!("{}", 5u64.to_str()); 25 | println!("{}", Some(&5u64).to_str()); 26 | println!("{}", Some(5u64).to_str()); 27 | println!("{}", None::<&u64>.to_str()); 28 | } 29 | -------------------------------------------------------------------------------- /rust-playground/src/bin/impl-trait-for-option-generic-solution.rs: -------------------------------------------------------------------------------- 1 | pub trait Str { 2 | fn to_str(&self) -> String; 3 | } 4 | 5 | impl Str for u64 { 6 | fn to_str(&self) -> String { 7 | format!("{}", self) 8 | } 9 | } 10 | 11 | impl> Str for Option { 12 | fn to_str(&self) -> String { 13 | self.as_ref().to_str() 14 | } 15 | } 16 | 17 | impl> Str for Option<&V> { 18 | fn to_str(&self) -> String { 19 | self.map(|x| x.to_str()).unwrap_or("-".to_string()) 20 | } 21 | } 22 | 23 | fn main() { 24 | println!("{}", 5u64.to_str()); 25 | println!("{}", Some(&5u64).to_str()); 26 | println!("{}", Some(5u64).to_str()); 27 | println!("{}", None::<&u64>.to_str()); 28 | } 29 | -------------------------------------------------------------------------------- /rust-playground/src/bin/iter-ref-self.rs: -------------------------------------------------------------------------------- 1 | use std::marker::PhantomData; 2 | 3 | struct It<'a> { 4 | i: i32, 5 | p: PhantomData<&'a ()>, 6 | } 7 | 8 | impl Drop for It<'_> { 9 | fn drop(&mut self) { 10 | self.i = 2; 11 | println!("dropped"); 12 | } 13 | } 14 | 15 | impl<'a> Iterator for It<'a> { 16 | type Item = &'a i32; 17 | 18 | fn next(&mut self) -> Option { 19 | let p = &self.i as *const i32; 20 | let x = unsafe { &*p }; 21 | 22 | Some(x) 23 | } 24 | } 25 | 26 | fn main() { 27 | let u = { 28 | let mut it = It { 29 | i: 1, 30 | p: PhantomData, 31 | }; 32 | it.next() 33 | }; 34 | 35 | println!("{:?}", u); 36 | } 37 | -------------------------------------------------------------------------------- /rust-playground/src/bin/macro_kv_default.rs: -------------------------------------------------------------------------------- 1 | trait RaftTypeConfig { 2 | type A; 3 | type B; 4 | type C; 5 | } 6 | 7 | macro_rules! impl2 { 8 | ($($name:ident = $type:ty),* ) => { 9 | impl2!(@F_0, $($name = $type,)* @T); 10 | }; 11 | 12 | // error: local ambiguity when calling macro `impl2`: multiple parsing options: built-in NTs ident ('n1') or 1 other option. 13 | // (@R_0, $($n1:ident = $t1:ty,)* A=$t: ty, $($n2:ident = $t2:ty,)* @T) => { 14 | // A=$t:ty, 15 | // impl2!(@R_1, $($n1 = $t1,)* $($n2 = $t2,)* @T); 16 | // }; 17 | // 18 | // (@R_1, $($n1:ident = $t1:ty,)* B=$t: ty, $($n2:ident = $t2:ty,)* @T) => { 19 | // B=$t:ty, 20 | // impl2!(@R_2, $($n1 = $t1,)* $($n2 = $t2,)* @T); 21 | // }; 22 | // 23 | // (@R_2, $($n1:ident = $t1:ty,)* C=$t: ty, $($n2:ident = $t2:ty,)* @T) => { 24 | // C=$t:ty, 25 | // }; 26 | 27 | (@F_0, A=$t: ty, $($name:ident = $type:ty,)* @T) => { 28 | type A = $t; 29 | impl2!(@F_1, $($name = $type,)* @T); 30 | }; 31 | 32 | (@F_0, $($name:ident = $type:ty,)* @T ) => { 33 | type A = Foo; 34 | impl2!(@F_1, $($name = $type,)* @T); 35 | }; 36 | 37 | (@F_1, B=$t: ty, $($name:ident = $type:ty,)* @T ) => { 38 | type B = $t; 39 | impl2!(@F_2, $($name = $type,)* @T); 40 | }; 41 | 42 | (@F_1, $($name:ident = $type:ty,)* @T ) => { 43 | type B = Bar; 44 | impl2!(@F_2, $($name = $type,)* @T); 45 | }; 46 | 47 | (@F_2, C=$t: ty, $($name:ident = $type:ty,)* @T ) => { 48 | type C = $t; 49 | impl2!(@F_ABC, $($name = $type,)* @T); 50 | }; 51 | 52 | (@F_2, $($name:ident = $type:ty,)* @T) => { 53 | type C = Wow; 54 | impl2!(@F_3, $($name = $type,)* @T); 55 | }; 56 | 57 | (@F_3, @T ) => { 58 | }; 59 | 60 | () => {}; 61 | } 62 | 63 | struct Foo {} 64 | 65 | impl RaftTypeConfig for Foo { 66 | impl2!(B = u16, A = u32); 67 | } 68 | 69 | // impl RaftTypeConfig for Foo { 70 | // impl2!(A = u32, B = u16, C = u8); 71 | // } 72 | // impl RaftTypeConfig for Foo { 73 | // impl2!(A = u32, B = u16); 74 | // } 75 | // impl RaftTypeConfig for Foo { 76 | // impl2!(A = u32, C = u8); 77 | // } 78 | // impl RaftTypeConfig for Foo { 79 | // impl2!(B = u16, C = u8); 80 | // } 81 | // impl RaftTypeConfig for Foo { 82 | // impl2!(A = u32); 83 | // } 84 | // impl RaftTypeConfig for Foo { 85 | // impl2!(B = u16); 86 | // } 87 | // impl RaftTypeConfig for Foo { 88 | // impl2!(C = u8); 89 | // } 90 | // impl RaftTypeConfig for Foo { 91 | // impl2!(); 92 | // } 93 | 94 | fn main() {} 95 | -------------------------------------------------------------------------------- /rust-playground/src/bin/map-api-send-cause-not-general-err.rs: -------------------------------------------------------------------------------- 1 | #![feature(type_alias_impl_trait)] 2 | 3 | use std::borrow::Borrow; 4 | use std::collections::BTreeMap; 5 | use std::future::Future; 6 | use std::sync::Arc; 7 | 8 | pub fn by_key_seq((k1, _v1): &(K, V), (k2, _v2): &(K, V)) -> bool 9 | where 10 | K: MapKey, 11 | { 12 | k1 <= k2 13 | } 14 | 15 | pub fn assert_send(v: T) -> T { 16 | v 17 | } 18 | 19 | pub fn assert_sync(v: T) -> T { 20 | v 21 | } 22 | 23 | #[derive(Debug, Clone, Default, PartialEq)] 24 | pub struct Val(u64); 25 | 26 | #[derive(Debug, Default)] 27 | pub struct Level { 28 | pub kv: BTreeMap, 29 | } 30 | 31 | #[derive(Debug, Default, Clone)] 32 | pub struct StaticLevels { 33 | levels: Vec>, 34 | } 35 | 36 | impl StaticLevels { 37 | pub fn new(levels: impl IntoIterator>) -> Self { 38 | Self { 39 | levels: levels.into_iter().collect(), 40 | } 41 | } 42 | 43 | pub fn iter_levels(&self) -> impl Iterator { 44 | self.levels.iter().map(|x| x.as_ref()).rev() 45 | } 46 | } 47 | 48 | pub trait MapKey: Clone + Ord + Send + Sync + Unpin + 'static { 49 | type V: Default + Clone + PartialEq + Send + Sync + Unpin + 'static; 50 | } 51 | 52 | impl MapKey for String { 53 | type V = Val; 54 | } 55 | 56 | pub trait MapApiRO: Send + Sync 57 | where 58 | K: MapKey, 59 | { 60 | type GetFut<'f, Q>: Future 61 | where 62 | Self: 'f, 63 | K: Borrow, 64 | Q: Ord + Send + Sync + ?Sized, 65 | Q: 'f; 66 | 67 | fn get<'f, Q>(self, key: &'f Q) -> Self::GetFut<'f, Q> 68 | where 69 | K: Borrow, 70 | Q: Ord + Send + Sync + ?Sized, 71 | Q: 'f; 72 | } 73 | 74 | impl<'d> MapApiRO for &'d Level { 75 | type GetFut<'f, Q> = impl Future::V> + 'f 76 | where 77 | Self: 'f, 78 | String: Borrow, 79 | Q: Ord + Send + Sync + ?Sized, 80 | Q: 'f; 81 | 82 | fn get<'f, Q>(self, key: &'f Q) -> Self::GetFut<'f, Q> 83 | where 84 | Self: 'f, 85 | String: Borrow, 86 | Q: Ord + Send + Sync + ?Sized, 87 | Q: 'f, 88 | { 89 | async move { self.kv.get(key).cloned().unwrap_or_default() } 90 | } 91 | } 92 | 93 | impl<'ro_d, K> MapApiRO for &'ro_d StaticLevels 94 | where 95 | K: MapKey, 96 | for<'e> &'e Level: MapApiRO, 97 | { 98 | type GetFut<'f,Q> = impl Future + 'f 99 | where 100 | Self: 'f, 101 | K: Borrow, 102 | Q: Ord + Send + Sync + ?Sized, 103 | Q: 'f; 104 | 105 | fn get<'f, Q>(self, key: &'f Q) -> Self::GetFut<'f, Q> 106 | where 107 | Self: 'f, 108 | K: Borrow, 109 | Q: Ord + Send + Sync + ?Sized, 110 | Q: 'f, 111 | { 112 | async move { 113 | for level_data in self.iter_levels() { 114 | let got = level_data.get(key).await; 115 | if got != K::V::default() { 116 | return got; 117 | } 118 | } 119 | K::V::default() 120 | } 121 | } 122 | } 123 | 124 | #[tokio::main] 125 | async fn main() { 126 | let k = || "a".to_string(); 127 | 128 | let static_levels = { 129 | let mut d1 = Level { 130 | kv: Default::default(), 131 | }; 132 | 133 | let mut d2 = Level { 134 | kv: Default::default(), 135 | }; 136 | 137 | d1.kv.insert(k(), Val(3)); 138 | d2.kv.insert(k(), Val(2)); 139 | 140 | StaticLevels::new([Arc::new(d1), Arc::new(d2)]) 141 | }; 142 | { 143 | let got = static_levels.get(&k()).await; 144 | assert_eq!(got, Val(2)); 145 | } 146 | 147 | { 148 | let x = k(); 149 | let fu = static_levels.get(x.as_str()); 150 | let fu = assert_sync(fu); 151 | } 152 | } 153 | -------------------------------------------------------------------------------- /rust-playground/src/bin/match-arm-stack-size.rs: -------------------------------------------------------------------------------- 1 | use std::fmt::Display; 2 | 3 | static mut RSP: isize = 0; 4 | 5 | fn print_stack_pos(msg: impl Display) { 6 | let a = (); 7 | let ptr = &a as *const _ as isize; 8 | let prev = unsafe { RSP }; 9 | 10 | println!("{:>5} stack ptr: {:x}, diff: {}", msg, ptr, prev - ptr); 11 | 12 | unsafe { 13 | RSP = ptr; 14 | } 15 | } 16 | 17 | fn inner() -> u8 { 18 | print_stack_pos("inner"); 19 | 0 20 | } 21 | 22 | fn outer_match() { 23 | let v = 0; 24 | // Every matching arm occupies a piece of memory on the stack. 25 | // Thus the stack memory for `inner()` starts will be 3KB after on the stack. 26 | match v { 27 | _ if v == 0 => inner(), 28 | _ if v == 1 => [0u8; 1024][0], 29 | _ if v == 2 => [0u8; 1024 * 2][0], 30 | _ => 0, 31 | }; 32 | } 33 | 34 | // allocate 2KB + 1KB on stack 35 | fn outer_blocks() { 36 | { 37 | inner(); 38 | } 39 | { 40 | let _c = [0u8; 1024]; 41 | } 42 | { 43 | let _c = [0u8; 1024 * 2]; 44 | } 45 | } 46 | 47 | // allocate 2KB on stack, then allocate 1KB on stack 48 | fn outer_blocks_2() { 49 | fn a() { 50 | let _c = [0u8; 1024]; 51 | } 52 | a(); 53 | 54 | { 55 | let _c = [0u8; 1024 * 2]; 56 | } 57 | } 58 | 59 | fn main() { 60 | print_stack_pos("main"); 61 | outer_match(); 62 | print_stack_pos("main"); 63 | outer_blocks(); 64 | } 65 | -------------------------------------------------------------------------------- /rust-playground/src/bin/min-specialization.rs: -------------------------------------------------------------------------------- 1 | #![feature(min_specialization)] 2 | 3 | trait Trait { 4 | fn desc(&self) -> String; 5 | } 6 | 7 | /* default impl */ 8 | impl Trait for T { 9 | default fn desc(&self) -> String { 10 | "something".to_string() 11 | } 12 | } 13 | 14 | /* specialized impl */ 15 | impl Trait for u64 { 16 | fn desc(&self) -> String { 17 | format!("{}", self) 18 | } 19 | } 20 | 21 | trait IterExt {} 22 | 23 | impl> IterExt for I {} /* default impl */ 24 | impl IterExt for std::vec::IntoIter {} /* specialized impl */ 25 | 26 | fn main() { 27 | println!("{}", 1u16.desc()); 28 | println!("{}", 1u32.desc()); 29 | println!("{}", 1u64.desc()); 30 | } 31 | -------------------------------------------------------------------------------- /rust-playground/src/bin/mixin.rs: -------------------------------------------------------------------------------- 1 | //! Provide methods via `AsRef` trait. 2 | 3 | trait RemoteVote { 4 | fn remote_vote(&self) -> u64; 5 | } 6 | 7 | impl RemoteVote for T 8 | where 9 | T: AsRef, 10 | { 11 | fn remote_vote(&self) -> u64 { 12 | self.as_ref().remote_vote() 13 | } 14 | } 15 | 16 | struct VoteStore { 17 | vote: u64, 18 | } 19 | 20 | impl RemoteVote for VoteStore { 21 | fn remote_vote(&self) -> u64 { 22 | self.vote 23 | } 24 | } 25 | 26 | trait RemoteLog { 27 | fn log_index(&self) -> u32; 28 | } 29 | 30 | impl RemoteLog for T 31 | where 32 | T: AsRef, 33 | { 34 | fn log_index(&self) -> u32 { 35 | self.as_ref().log_index() 36 | } 37 | } 38 | 39 | struct LogStore { 40 | log: u32, 41 | } 42 | 43 | impl RemoteLog for LogStore { 44 | fn log_index(&self) -> u32 { 45 | self.log 46 | } 47 | } 48 | 49 | #[derive(derive_more::AsRef)] 50 | struct My { 51 | #[as_ref] 52 | vote_store: VoteStore, 53 | #[as_ref] 54 | log_store: LogStore, 55 | } 56 | 57 | fn main() { 58 | let my = My { 59 | vote_store: VoteStore { vote: 3 }, 60 | log_store: LogStore { log: 4 }, 61 | }; 62 | 63 | println!("{}", my.remote_vote()); 64 | println!("{}", my.log_index()); 65 | } 66 | -------------------------------------------------------------------------------- /rust-playground/src/bin/mut-ref-to-ref-require-lifetime-constraint.rs: -------------------------------------------------------------------------------- 1 | // 想分别从结构体 Ref 和 RefMut 中拿出 &T, 2 | // 遇到了 &T 和 &mut T 对生命周期的要求不一样的问题: 3 | // RefMut::get() 额外要求 `'me: 'out` 4 | // 5 | // 因为 &mut T 不是 Copy 的, 6 | // 要使用 &T 就必须保证这期间 &'me self 不被 drop, 7 | // 否则会导致 &'d mut T 在 'd 的生命周期内有第2个引用而破坏借用原则. 8 | 9 | struct Ref<'d> { 10 | data: &'d (), 11 | } 12 | struct RefMut<'d> { 13 | data: &'d mut (), 14 | } 15 | 16 | impl<'d> Ref<'d> { 17 | fn get<'me, 'o>(&'me self) -> &'o () 18 | where 19 | 'd: 'o, 20 | { 21 | self.data 22 | } 23 | } 24 | 25 | impl<'d> RefMut<'d> { 26 | fn get<'me, 'out>(&'me mut self) -> &'out () 27 | where 28 | 'd: 'out, 29 | // Without `where 'me: 'out`: 30 | // 36 | self.data 31 | // | ^^^^^^^^^ associated function was supposed 32 | // | to return data with lifetime `'out` but it 33 | // | is returning data with lifetime `'me`. 34 | 'me: 'out, 35 | { 36 | self.data 37 | } 38 | } 39 | 40 | fn main() { 41 | let mut d = (); 42 | Ref { data: &mut d }.get(); 43 | RefMut { data: &mut d }.get(); 44 | } 45 | -------------------------------------------------------------------------------- /rust-playground/src/bin/non-implementable-trait-method.rs: -------------------------------------------------------------------------------- 1 | pub mod foo { 2 | 3 | pub trait Trait { 4 | /// This method is unimplementable by users, 5 | /// because it references a trait in a private mod `sealed` 6 | fn unimplementable(&self) 7 | where 8 | Self: sealed::Sealed, 9 | { 10 | self.user_impl_this(); 11 | } 12 | 13 | fn user_impl_this(&self); 14 | } 15 | 16 | mod sealed { 17 | pub trait Sealed {} 18 | impl Sealed for T {} 19 | } 20 | } 21 | 22 | //////////////////////////////////////////////////////// 23 | 24 | pub struct Implementor; 25 | 26 | impl foo::Trait for Implementor { 27 | fn unimplementable(&self) 28 | where 29 | Self: foo::sealed::Sealed, 30 | { 31 | todo!() 32 | } 33 | 34 | fn user_impl_this(&self) { 35 | println!("user_impl_this"); 36 | } 37 | } 38 | 39 | fn main() {} 40 | -------------------------------------------------------------------------------- /rust-playground/src/bin/not-send.rs: -------------------------------------------------------------------------------- 1 | use std::marker::PhantomData; 2 | 3 | fn accept_send(_t: T) {} 4 | 5 | #[derive(Default)] 6 | struct NotSend { 7 | p: PhantomData<*const ()>, 8 | } 9 | 10 | struct Foo { 11 | c: T::Inner, 12 | p: PhantomData, 13 | } 14 | 15 | trait Types: Send + Sync { 16 | type Inner; 17 | } 18 | 19 | struct Config; 20 | 21 | impl Types for Config { 22 | type Inner = NotSend; 23 | } 24 | 25 | impl Types for NotSend { 26 | type Inner = (); 27 | } 28 | 29 | fn main() { 30 | let a = NotSend { 31 | p: PhantomData::default(), 32 | }; 33 | 34 | accept_send(Foo:: { 35 | c: Default::default(), 36 | p: PhantomData::default(), 37 | }); 38 | } 39 | -------------------------------------------------------------------------------- /rust-playground/src/bin/pattern-in-arg.rs: -------------------------------------------------------------------------------- 1 | struct Foo { 2 | a: u64, 3 | b: u64, 4 | } 5 | 6 | fn doit(Foo { a, .. }: Foo) { 7 | println!("{a}"); 8 | } 9 | 10 | fn main() { 11 | doit(Foo { a: 3, b: 4 }); 12 | } 13 | -------------------------------------------------------------------------------- /rust-playground/src/bin/pin-a-value.rs: -------------------------------------------------------------------------------- 1 | #![feature(type_name_of_val)] 2 | 3 | use futures_util::FutureExt; 4 | use std::future::Future; 5 | use std::pin::Pin; 6 | 7 | async fn no_pin>(fu: Fu) { 8 | fu.now_or_never(); 9 | } 10 | 11 | async fn std_pin>(fu: Fu) { 12 | // Expand to: 13 | // let pinned = ::core::pin::Pin::<&mut _> { 14 | // pointer: &mut { fu }, 15 | // }; 16 | let pinned: Pin<&mut Fu> = std::pin::pin!(fu); 17 | 18 | pinned.await; 19 | } 20 | 21 | async fn futures_pin_mut>(fu: Fu) { 22 | // Expand to 23 | // let mut fu = fu; 24 | // #[allow(unused_mut)] 25 | // let mut fu = unsafe { ::pin_utils::core_reexport::pin::Pin::new_unchecked(&mut fu) }; 26 | futures::pin_mut!(fu); 27 | 28 | let pinned: Pin<&mut Fu> = fu; 29 | 30 | pinned.await; 31 | } 32 | 33 | async fn futures_pin_mut_loop_value_moved>(fu: Fu) { 34 | loop { 35 | // Compilation error: value moved: fu 36 | // futures::pin_mut!(fu); 37 | break; 38 | } 39 | let _ = fu; 40 | } 41 | 42 | async fn std_pin_loop_value_moved>(fu: Fu) { 43 | loop { 44 | // Compilation error: Value moved: fu 45 | // let pinned = std::pin::pin!(fu); 46 | break; 47 | } 48 | let _ = fu; 49 | } 50 | 51 | async fn std_pin_outside_loop>(fu: Fu) { 52 | let mut pinned = std::pin::pin!(fu); 53 | loop { 54 | let pinned = pinned.as_mut(); 55 | pinned.await; 56 | break; 57 | } 58 | } 59 | 60 | fn main() { 61 | futures::executor::block_on(async move { 62 | let fu = async { () }; 63 | futures_pin_mut(fu).await; 64 | 65 | let fu = async { () }; 66 | std_pin_loop_value_moved(fu).await; 67 | 68 | let fu = async { () }; 69 | futures_pin_mut_loop_value_moved(fu).await; 70 | 71 | let fu = async { () }; 72 | std_pin_outside_loop(fu).await; 73 | }); 74 | } 75 | -------------------------------------------------------------------------------- /rust-playground/src/bin/ref-vs-ref-keyword.rs: -------------------------------------------------------------------------------- 1 | #![feature(custom_inner_attributes)] 2 | #![rustfmt::skip] 3 | struct Foo { 4 | writer: Option, 5 | } 6 | 7 | impl Foo { 8 | fn ref_keyword_is_ok(&mut self) -> &mut u64 { 9 | if let Some(ref mut w) = self.writer { // 10 | w // Scope of `&mut self.writer` ends here 11 | } else { // 12 | self.writer.insert(5) // 13 | } // 14 | } 15 | 16 | fn as_mut_does_not_compile(&mut self) -> &mut u64 { 17 | if let Some(w) = self.writer.as_mut() { // 18 | w // 19 | } else { // 20 | self.writer.insert(5) // 21 | } // Scope of `&mut self.writer` lasts as long as the if-let statement, 22 | // and ends here 23 | } 24 | 25 | fn no_return_value_ok(&mut self) { 26 | if let Some(w) = self.writer.as_mut() { 27 | w 28 | } else { 29 | self.writer.insert(5) 30 | }; 31 | } 32 | } 33 | 34 | fn main() {} 35 | -------------------------------------------------------------------------------- /rust-playground/src/bin/return-position-2.rs: -------------------------------------------------------------------------------- 1 | trait Trait { 2 | fn trait_ids<'s>(&'s self) -> impl Iterator + 'static; 3 | } 4 | 5 | struct Foo { 6 | ids: Vec, 7 | } 8 | 9 | impl Foo { 10 | fn ids<'s>(&'s self) -> impl Iterator + 'static { 11 | self.ids.clone().into_iter() 12 | } 13 | } 14 | 15 | impl Trait for Foo { 16 | fn trait_ids<'s>(&'s self) -> impl Iterator + 'static { 17 | self.ids.clone().into_iter() 18 | } 19 | } 20 | 21 | impl<'f> Trait for &'f Foo { 22 | fn trait_ids<'s>(&'s self) -> impl Iterator + 'static { 23 | self.ids.clone().into_iter() 24 | } 25 | } 26 | 27 | fn main() { 28 | let u = { 29 | let f = Foo { ids: vec![] }; 30 | Trait::trait_ids(&&f) 31 | }; 32 | 33 | let u = { Foo { ids: vec![] }.ids() }; 34 | println!("{:?}", u.collect::>()); 35 | // Good! 36 | 37 | let u = { Foo { ids: vec![] }.trait_ids() }; 38 | println!("{:?}", u.collect::>()); 39 | // Compile error in an old version of Rust: 40 | // error[E0716]: temporary value dropped while borrowed 41 | // --> src/bin/return-position-2.rs:23:16 42 | // | 43 | // 23 | let _u = { Foo { ids: vec![] }.trait_ids() }; 44 | // | ^^^^^^^^^^^^^^^^^^^ - temporary value is freed at the end of this statement 45 | // | | 46 | // | creates a temporary value which is freed while still in use 47 | // 24 | } 48 | // | - borrow might be used here, when `_u` is dropped and runs the destructor for type `impl Iterator + 'static` 49 | // | 50 | // = note: consider using a `let` binding to create a longer lived value 51 | } 52 | -------------------------------------------------------------------------------- /rust-playground/src/bin/return-position.rs: -------------------------------------------------------------------------------- 1 | struct Foo { 2 | ids: Vec, 3 | } 4 | 5 | struct Ref { 6 | r: T, 7 | } 8 | 9 | trait Trait<'r> { 10 | fn ids<'s>(&'s self) -> impl Iterator + 'r; 11 | } 12 | 13 | impl<'a> Trait<'static> for Ref<&'a Foo> { 14 | fn ids<'s>(&'s self) -> impl Iterator + 'static { 15 | self.r.ids.clone().into_iter() 16 | } 17 | } 18 | 19 | impl Foo { 20 | // `ids()` does not capture lifetime of `self`. But it does not seem to work: 21 | // https://rust-lang.github.io/rfcs/3498-lifetime-capture-rules-2024.html#appendix-e-adding-a-static-bound 22 | // 23 | // edition 2024: 24 | // 25 | // error[E0597]: `r` does not live long enough 26 | // --> src/bin/return-position.rs:22:19 27 | // | 28 | // 20 | fn get_ids<'a>(&'a self) -> impl Iterator + 'static { 29 | // | -- lifetime `'a` defined here 30 | // 21 | let r: Ref<&'a Foo> = Ref { r: self }; 31 | // | - binding `r` declared here 32 | // 22 | let ids = r.ids(); 33 | // | ^------ 34 | // | | 35 | // | borrowed value does not live long enough 36 | // | argument requires that `r` is borrowed for `'a` 37 | // 23 | ids 38 | // 24 | } 39 | // | - `r` dropped here while still borrowed 40 | fn get_ids<'a>(&'a self) -> impl Iterator + 'static { 41 | let r: Ref<&'a Foo> = Ref { r: self }; 42 | let ids = r.ids(); 43 | ids 44 | } 45 | } 46 | 47 | fn main() { 48 | let u = { Foo { ids: vec![] }.get_ids() }; 49 | println!("{:?}", u.collect::>()); 50 | } 51 | -------------------------------------------------------------------------------- /rust-playground/src/bin/return_position_impl_trait_in_trait-stable.rs: -------------------------------------------------------------------------------- 1 | #[async_trait::async_trait] 2 | pub trait MapApiRO: Send + Sync { 3 | /// Get an entry by key. 4 | async fn get(&self, key: &K) -> (); 5 | } 6 | 7 | pub trait AsMap { 8 | // Will be stabilized in 1.75 9 | fn as_map(&self) -> &impl MapApiRO 10 | where 11 | Self: MapApiRO + Sized, 12 | { 13 | self 14 | } 15 | } 16 | 17 | fn main() {} 18 | -------------------------------------------------------------------------------- /rust-playground/src/bin/serde-bound.rs: -------------------------------------------------------------------------------- 1 | pub trait NodeId: serde::Serialize + for<'a> serde::Deserialize<'a> {} 2 | 3 | #[derive(serde::Deserialize, serde::Serialize)] 4 | #[serde(bound = "")] 5 | pub enum Fatal 6 | where 7 | NID: NodeId, 8 | { 9 | StorageError(NID), 10 | } 11 | 12 | #[derive(serde::Deserialize, serde::Serialize)] 13 | // #[serde(bound = "E: serde::Serialize + for <'d> serde::Deserialize<'d>")] 14 | #[serde(bound(serialize = "E: serde::Serialize"))] 15 | #[serde(bound(deserialize = "E: for <'d> serde::Deserialize<'d>"))] 16 | struct MyError 17 | where 18 | NID: NodeId, 19 | E: std::error::Error, 20 | { 21 | nid: NID, 22 | err: E, 23 | } 24 | 25 | fn main() {} 26 | -------------------------------------------------------------------------------- /rust-playground/src/bin/specialization-with-autoref.rs: -------------------------------------------------------------------------------- 1 | //! This does not work: 2 | //! ```ignore 3 | //! struct Echoable { 4 | //! _p: PhantomData, 5 | //! } 6 | //! <(&&Echoable)>::echo(); 7 | //! // function or associated item not found in `&&Echoable 8 | //! // No autoref 9 | //! ``` 10 | use std::fmt::Debug; 11 | 12 | struct Echoable(T); 13 | 14 | trait Echo { 15 | fn echo(&self); 16 | } 17 | 18 | impl Echo for &&Echoable { 19 | fn echo(&self) { 20 | println!("u64: {}", self.0); 21 | } 22 | } 23 | 24 | impl Echo for &Echoable { 25 | fn echo(&self) { 26 | println!("Debug: {:?}", self.0); 27 | } 28 | } 29 | 30 | impl Echo for Echoable { 31 | fn echo(&self) { 32 | println!("generic"); 33 | } 34 | } 35 | 36 | struct Foo; 37 | 38 | fn main() { 39 | (&&&Echoable(Foo)).echo(); // generic 40 | (&&&Echoable("str")).echo(); // Debug: "str" 41 | (&&&Echoable(1u64)).echo(); // u64: 1 42 | (&&Echoable(1u64)).echo(); // Debug: 1 43 | (&Echoable(1u64)).echo(); // generic 44 | } 45 | -------------------------------------------------------------------------------- /rust-playground/src/bin/specialization.rs: -------------------------------------------------------------------------------- 1 | #![feature(specialization)] 2 | 3 | trait Trait { 4 | fn desc(&self) -> String; 5 | } 6 | 7 | /* default impl */ 8 | impl Trait for T { 9 | default fn desc(&self) -> String { 10 | "something".to_string() 11 | } 12 | } 13 | 14 | /* specialized impl */ 15 | impl Trait for u64 { 16 | // Default impl does not work: 17 | // 18 | // error[E0520]: `desc2` specializes an item from a parent `impl`, but that item is not marked `default` 19 | // --> src/bin/specialization.rs:34:5 20 | // | 21 | // 30 | impl TraitWithDefaultImpl for T {} 22 | // | ---------------------------------- parent `impl` is here 23 | // ... 24 | // 34 | / fn desc2(&self) -> String { 25 | // 35 | | format!("{}", self) 26 | // 36 | | } 27 | // | |_____^ cannot specialize default item `desc2` 28 | // | 29 | // = note: to specialize, `desc2` in the parent `impl` must be marked `default` 30 | fn desc(&self) -> String { 31 | format!("{}", self) 32 | } 33 | } 34 | 35 | // --- 36 | 37 | /* default impl in trait definition */ 38 | trait TraitWithDefaultImpl { 39 | fn desc2(&self) -> String { 40 | "unknown_desc".to_string() 41 | } 42 | } 43 | 44 | impl TraitWithDefaultImpl for T {} 45 | 46 | /* specialized impl */ 47 | impl TraitWithDefaultImpl for u64 { 48 | fn desc2(&self) -> String { 49 | format!("{}", self) 50 | } 51 | } 52 | 53 | // --- 54 | 55 | trait IterExt {} 56 | 57 | impl> IterExt for I {} /* default impl */ 58 | impl IterExt for std::vec::IntoIter {} /* specialized impl */ 59 | 60 | fn main() { 61 | println!("{}", 1u16.desc()); 62 | println!("{}", 1u32.desc()); 63 | println!("{}", 1u64.desc()); 64 | 65 | println!("{}", 1u16.desc2()); 66 | println!("{}", 1u64.desc2()); 67 | } 68 | -------------------------------------------------------------------------------- /rust-playground/src/bin/static-param.rs: -------------------------------------------------------------------------------- 1 | struct Foo<'d> { 2 | d: &'d (), 3 | } 4 | 5 | fn foo(v: T) -> T { 6 | v 7 | } 8 | 9 | trait Doit { 10 | fn doit(&self) {} 11 | } 12 | 13 | impl Doit for T where T: Send + Sync + 'static {} 14 | 15 | fn main() { 16 | let f = Foo { d: &() }; 17 | let f = foo(f); 18 | f.doit(); 19 | } 20 | -------------------------------------------------------------------------------- /rust-playground/src/bin/stream-map.rs: -------------------------------------------------------------------------------- 1 | use futures_util::StreamExt; 2 | use std::future; 3 | 4 | // #[tokio::main] 5 | // async fn main() { 6 | // let strm = futures::stream::iter([1, 2, 3]); 7 | // let s2 = strm 8 | // .take_while(|x| future::ready(x < &2)) 9 | // .map(|x| if x < 2 { Some(x) } else { None }); 10 | // let got = s2.collect::>().await; 11 | // println!("{:?}", got) 12 | // } 13 | 14 | use std::fmt; 15 | 16 | struct Person { 17 | name: String, 18 | age: u32, 19 | } 20 | 21 | impl fmt::Debug for Person { 22 | fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { 23 | f.debug_struct("Person") 24 | .field("name", &self.name) 25 | .field("age", &self.age) 26 | .finish() 27 | } 28 | } 29 | 30 | fn main() { 31 | let person = Person { 32 | name: String::from("Alice"), 33 | age: 30, 34 | }; 35 | 36 | println!("{:?}", person); 37 | println!("{:#?}", person); 38 | } 39 | -------------------------------------------------------------------------------- /rust-playground/src/bin/thread_local_attr_not_dropped.rs: -------------------------------------------------------------------------------- 1 | #![feature(thread_local)] 2 | 3 | struct Foo(usize); 4 | impl Drop for Foo { 5 | fn drop(&mut self) { 6 | println!("dropped"); 7 | } 8 | } 9 | 10 | #[thread_local] 11 | static mut ATTR_TLS: Foo = Foo(0); 12 | 13 | fn main() { 14 | let _ = std::thread::spawn(|| unsafe { 15 | println!("foo: {}", ATTR_TLS.0); 16 | }) 17 | .join(); 18 | } 19 | -------------------------------------------------------------------------------- /rust-playground/src/bin/thread_local_macro_drop.rs: -------------------------------------------------------------------------------- 1 | struct Foo(usize); 2 | impl Drop for Foo { 3 | fn drop(&mut self) { 4 | println!("dropped"); 5 | } 6 | } 7 | 8 | thread_local! { 9 | static MACRO_TLS: std::cell::RefCell = std::cell::RefCell::new(Foo(0)); 10 | } 11 | 12 | fn main() { 13 | let _ = std::thread::spawn(|| unsafe { 14 | MACRO_TLS.with(|f| { 15 | println!("foo: {}", f.borrow_mut().0); 16 | }); 17 | }) 18 | .join(); 19 | } 20 | -------------------------------------------------------------------------------- /rust-playground/src/bin/tokio-shutdown.rs: -------------------------------------------------------------------------------- 1 | use tokio::runtime::Runtime; 2 | use tokio::task; 3 | 4 | use std::thread; 5 | use std::time::Duration; 6 | 7 | fn main() { 8 | let runtime = Runtime::new().unwrap(); 9 | 10 | runtime.block_on(async move { 11 | task::spawn_blocking(move || { 12 | thread::sleep(Duration::from_secs(10_000)); 13 | println!("fnishing up"); 14 | }); 15 | }); 16 | 17 | runtime.shutdown_timeout(Duration::from_millis(100)); 18 | } 19 | -------------------------------------------------------------------------------- /rust-playground/src/bin/tokio-unbounded-recv-select.rs: -------------------------------------------------------------------------------- 1 | use futures::future::FutureExt; 2 | use std::pin::pin; 3 | 4 | #[tokio::main] 5 | async fn main() { 6 | // Use select() 7 | { 8 | let (tx, mut rx) = tokio::sync::mpsc::unbounded_channel::<()>(); 9 | 10 | let fu = rx.recv(); 11 | let sleep = tokio::time::sleep(std::time::Duration::from_secs(1)); 12 | 13 | let fpin = pin!(fu); 14 | let spin = pin!(sleep); 15 | 16 | futures::future::select(fpin, spin).await; 17 | } 18 | 19 | // Use futures::select_biased!() 20 | { 21 | let (_tx, mut rx) = tokio::sync::mpsc::unbounded_channel::<()>(); 22 | 23 | let sleep = tokio::time::sleep(std::time::Duration::from_secs(1)); 24 | 25 | loop { 26 | futures::select_biased!( 27 | _ = rx.recv().fuse() => { 28 | println!("recv completed"); 29 | break; 30 | } 31 | _ = sleep.fuse() => { 32 | println!("sleep completed"); 33 | break; 34 | } 35 | ); 36 | } 37 | } 38 | } 39 | -------------------------------------------------------------------------------- /rust-playground/src/bin/try-logcall.rs: -------------------------------------------------------------------------------- 1 | #![feature(try_blocks)] 2 | fn main() -> anyhow::Result<()> { 3 | let x: Result<(), u64> = try { 4 | println!("Hello, world!"); 5 | return Err(anyhow::anyhow!("error")); 6 | }; 7 | 8 | println!("foo"); 9 | Ok(()) 10 | } 11 | -------------------------------------------------------------------------------- /rust-playground/src/bin/x.rs: -------------------------------------------------------------------------------- 1 | #![feature(pin_macro)] 2 | 3 | use std::future::Future; 4 | use std::marker::PhantomData; 5 | use std::pin::Pin; 6 | use std::task::{Context, Poll}; 7 | 8 | struct Get<'a> 9 | where 10 | Self: 'a, 11 | { 12 | value: Box, 13 | r: &'a i32, 14 | } 15 | 16 | impl<'a> Get<'a> 17 | where 18 | Self: 'a, 19 | { 20 | fn new(value: i32) -> Self { 21 | let b = Box::new(value); 22 | let r = unsafe { &*((&*b) as *const i32) }; 23 | Self { value: b, r } 24 | } 25 | 26 | fn get_r<'b>(&'b self) -> &'a i32 27 | where 28 | 'b: 'a, 29 | { 30 | self.r 31 | } 32 | } 33 | 34 | impl<'a> Future for Get<'a> 35 | where 36 | Self: 'a, 37 | { 38 | type Output = &'a i32 where Self: 'a; 39 | 40 | fn poll(self: Pin<&mut Self>, _cx: &mut Context<'_>) -> Poll { 41 | Poll::Ready(self.r) 42 | } 43 | } 44 | 45 | fn main() { 46 | // let got = { 47 | // let mut a = Get::new(2); 48 | // a.get_r() 49 | // }; 50 | 51 | let cx = &mut Context::from_waker(futures::task::noop_waker_ref()); 52 | let got = { 53 | let mut a = Get::new(2); 54 | let fu = std::pin::pin!(a); 55 | let got = fu.poll(cx); 56 | got 57 | }; 58 | 59 | dbg!(got); 60 | } 61 | -------------------------------------------------------------------------------- /rust-playground/src/bin/y.rs: -------------------------------------------------------------------------------- 1 | use std::future::Future; 2 | use std::pin::Pin; 3 | use std::task::{Context, Poll}; 4 | 5 | struct Container { 6 | value: i32, 7 | } 8 | 9 | struct ContainerFuture<'a> { 10 | container: Option<&'a mut Container>, 11 | } 12 | 13 | impl<'a> Future for ContainerFuture<'a> { 14 | type Output = &'a i32; 15 | 16 | fn poll(self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll { 17 | todo!() 18 | // Poll::Ready(&self.container.as_mut().unwrap().value) 19 | } 20 | } 21 | 22 | fn ck<'a, Fut>(f: Fut) 23 | where 24 | Fut: Future, 25 | { 26 | } 27 | 28 | fn main() { 29 | let x = 1i32; 30 | let q = async { &x }; 31 | ck(q); 32 | } 33 | -------------------------------------------------------------------------------- /rust-playground/src/bin/yy.rs: -------------------------------------------------------------------------------- 1 | #[derive(serde::Serialize, serde::Deserialize, Debug, Default, Clone, Eq, PartialEq)] 2 | pub struct KVMeta { 3 | /// expiration time in second since 1970 4 | pub(crate) expire_at: u64, 5 | } 6 | 7 | fn main() { 8 | let got: KVMeta = serde_json::from_str(r#"{"expire_at":1,"foo":2}"#).unwrap(); 9 | println!("{:?}", got) 10 | } 11 | -------------------------------------------------------------------------------- /rust-playground/src/bin/z.rs: -------------------------------------------------------------------------------- 1 | struct Foo { 2 | f: u64, 3 | } 4 | struct Goo<'g> { 5 | g: &'g u64, 6 | } 7 | 8 | fn doit<'g, 'f>(foo: &'f Foo) -> Goo<'g> { 9 | Goo { g: &foo.f } 10 | } 11 | 12 | fn it<'g>(g: &'g Goo) -> impl Iterator { 13 | std::iter::once(&3) 14 | } 15 | 16 | fn main() { 17 | let a = Foo { f: 3 }; 18 | { 19 | let b; 20 | { 21 | let r = &a; 22 | b = Goo { g: &r.f }; 23 | } 24 | println!("{}", b.g); 25 | } 26 | 27 | // let b = a.doit(); 28 | } 29 | -------------------------------------------------------------------------------- /rust-playground/t-cfg/.cargo/config.toml: -------------------------------------------------------------------------------- 1 | # [build] 2 | # rustflags = ["--cfg", "foo_config"] 3 | -------------------------------------------------------------------------------- /rust-playground/t-cfg/.gitignore: -------------------------------------------------------------------------------- 1 | /target 2 | 3 | Cargo.lock 4 | 5 | .DS_Store 6 | -------------------------------------------------------------------------------- /rust-playground/t-cfg/Cargo.toml: -------------------------------------------------------------------------------- 1 | # cargo-features = ["profile-rustflags"] 2 | 3 | [package] 4 | name = "t-cfg" 5 | version = "0.1.0" 6 | edition = "2021" 7 | 8 | # See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html 9 | 10 | [dependencies] 11 | 12 | -------------------------------------------------------------------------------- /rust-playground/t-cfg/src/main.rs: -------------------------------------------------------------------------------- 1 | // To enable a `#[cfg(xx)]` compilation condition: 2 | // 3 | // cargo --config 'build.rustflags = ["--cfg", "foo_config"]' run 4 | // 5 | // RUSTFLAGS='--cfg foo_config' cargo run 6 | // 7 | // cat ./cargo/config.toml 8 | // [build] 9 | // rustflags = ["--cfg", "foo_config"] 10 | // 11 | // Under the hood it is: 12 | // rustc --cfg some_condition custom.rs 13 | // 14 | // Reference: 15 | // cargo config: 16 | // https://doc.rust-lang.org/cargo/reference/config.html 17 | // 18 | // rustc CLI args: 19 | // https://doc.rust-lang.org/rustc/command-line-arguments.html#--cfg-configure-the-compilation-environment 20 | 21 | fn main() { 22 | #[cfg(foo_config)] 23 | println!("foo_config is enabled!"); 24 | } 25 | -------------------------------------------------------------------------------- /rust-playground/t-detect-nightly/.gitignore: -------------------------------------------------------------------------------- 1 | /target 2 | 3 | Cargo.lock 4 | 5 | .DS_Store 6 | -------------------------------------------------------------------------------- /rust-playground/t-detect-nightly/Cargo.toml: -------------------------------------------------------------------------------- 1 | [package] 2 | name = "t-detect-nightly" 3 | version = "0.1.0" 4 | edition = "2021" 5 | 6 | # See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html 7 | 8 | [dependencies] 9 | -------------------------------------------------------------------------------- /rust-playground/t-detect-nightly/build.rs: -------------------------------------------------------------------------------- 1 | use std::env; 2 | use std::process::Command; 3 | use std::str; 4 | 5 | fn main() { 6 | // from anyhow 7 | let rustc = env::var_os("RUSTC").unwrap(); 8 | let output = Command::new(rustc).arg("--version").output().unwrap(); 9 | let version = str::from_utf8(&output.stdout).unwrap(); 10 | let is_nightly = version.contains("nightly") || version.contains("dev") 11 | if is_nightly { 12 | println!("cargo:rustc-cfg=rustc_nightly"); 13 | } 14 | 15 | // With RUSTUP_TOOLCHAIN 16 | // https://stackoverflow.com/questions/59542378/conditional-compilation-for-nightly-vs-stable-rust-or-compiler-version 17 | let rust_toolchain = env::var("RUSTUP_TOOLCHAIN").unwrap(); 18 | if rust_toolchain.starts_with("stable") { 19 | // do nothing 20 | } else if rust_toolchain.starts_with("nightly") { 21 | //enable the 'nightly-features' feature flag 22 | println!("cargo:rustc-cfg=feature=\"env_nightly\""); 23 | } else { 24 | panic!("Unexpected value for rustc toolchain") 25 | } 26 | } 27 | 28 | -------------------------------------------------------------------------------- /rust-playground/t-detect-nightly/src/main.rs: -------------------------------------------------------------------------------- 1 | // Detect nightly rust with `build.rs`: 2 | // It output a compilation condition `foo_nightly` and a feature `bar_nightly` 3 | // 4 | // Test: 5 | // cargo +stable run 6 | // cargo +nightly run 7 | fn main() { 8 | #[cfg(foo_nightly)] 9 | println!("foo_nightly"); 10 | 11 | #[cfg(feature = "bar_nightly")] 12 | println!("bar_nightly"); 13 | } 14 | -------------------------------------------------------------------------------- /rust-playground/t-monoio/.gitignore: -------------------------------------------------------------------------------- 1 | /.idea 2 | /target 3 | Cargo.lock 4 | -------------------------------------------------------------------------------- /rust-playground/t-monoio/Cargo.toml: -------------------------------------------------------------------------------- 1 | [package] 2 | name = "t-monoio" 3 | version = "0.1.0" 4 | edition = "2021" 5 | 6 | # See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html 7 | 8 | [dependencies] 9 | monoio = { version = "0.2.2", features = ["sync"] } 10 | -------------------------------------------------------------------------------- /rust-playground/t-monoio/src/bin/cross-rt-join.rs: -------------------------------------------------------------------------------- 1 | //! Test if JoinHandle can be used in another thread. 2 | //! 3 | //! - Without enabling `sync` feature flag, `JoinHandle.await` sometimes blocks forever. 4 | //! - With `sync` feature flag enabled, `JoinHandle.await` returns correctly. But block forever if the task panics. 5 | //! 6 | //! Thanks to @Miaxos 7 | //! https://github.com/bytedance/monoio/issues/241#issuecomment-1950230596 8 | 9 | use std::sync::mpsc; 10 | use std::time::Duration; 11 | 12 | fn main() { 13 | let (tx, rx) = mpsc::channel(); 14 | 15 | std::thread::spawn(move || { 16 | let mut rt = monoio::RuntimeBuilder::::new() 17 | .enable_all() 18 | .build() 19 | .expect("Failed building the Runtime"); 20 | 21 | rt.block_on(async move { 22 | let fu = async move { 23 | // println!("inner-fu: ready"); 24 | // panic!("inner-fu: panic"); 25 | 1u64 26 | }; 27 | 28 | let handle = monoio::spawn(fu); 29 | tx.send(handle).unwrap(); 30 | 31 | monoio::time::sleep(Duration::from_millis(1_000)).await; 32 | println!("outer-fu: after sending handle and sleep"); 33 | }); 34 | }); 35 | 36 | let handle = rx.recv().unwrap(); 37 | 38 | let mut rt = monoio::RuntimeBuilder::::new() 39 | .enable_all() 40 | .build() 41 | .expect("Failed building the Runtime"); 42 | 43 | rt.block_on(async move { 44 | println!("joiner: before handle.await"); 45 | let got = handle.await; 46 | println!("joiner: after handle.await: {:?}", got); 47 | }); 48 | } 49 | -------------------------------------------------------------------------------- /rust-playground/t-monoio/src/bin/foo.rs: -------------------------------------------------------------------------------- 1 | #[monoio::main] 2 | async fn main() { 3 | } 4 | -------------------------------------------------------------------------------- /rust-playground/t-monoio/src/main.rs: -------------------------------------------------------------------------------- 1 | use std::sync::mpsc; 2 | use std::time::Duration; 3 | 4 | fn main() { 5 | let (tx, rx) = mpsc::channel(); 6 | 7 | std::thread::spawn(move || { 8 | monoio::RuntimeBuilder::::new() 9 | .enable_all() 10 | .build() 11 | .expect("Failed building the Runtime") 12 | .block_on(async move { 13 | let fu = async move { 14 | monoio::time::sleep(Duration::from_millis(500)).await; 15 | println!("inner-fu: before panic!"); 16 | // panic!("test"); 17 | 1u64 18 | }; 19 | 20 | println!("outer-fu: before spawn"); 21 | let handle = monoio::spawn(fu); 22 | tx.send(handle).unwrap(); 23 | println!("outer-fu: after tx.send"); 24 | 25 | monoio::time::sleep(Duration::from_millis(1_000)).await; 26 | println!("outer-fu: after sleep"); 27 | }); 28 | 29 | println!("thread-1: after block_on"); 30 | }); 31 | 32 | // std::thread::sleep(Duration::from_millis(2_000)); 33 | 34 | let handle = rx.recv().unwrap(); 35 | 36 | println!("main: before block_on"); 37 | let mut rt = monoio::RuntimeBuilder::::new() 38 | .enable_all() 39 | .build() 40 | .expect("Failed building the Runtime"); 41 | 42 | rt.block_on(async move { 43 | println!("joiner: before handle.await"); 44 | let got = handle.await; 45 | println!("joiner: after handle.await: {:?}", got); 46 | }); 47 | } 48 | -------------------------------------------------------------------------------- /rust-playground/t-monoio/src/monoio-main.rs: -------------------------------------------------------------------------------- 1 | #![feature(prelude_import)] 2 | #[prelude_import] 3 | use std::prelude::rust_2021::*; 4 | #[macro_use] 5 | extern crate std; 6 | #[allow(dead_code)] 7 | fn main() { 8 | let body = async {}; 9 | #[allow(clippy::expect_used)] 10 | monoio::RuntimeBuilder::::new() 11 | .build() 12 | .expect("Failed building the Runtime") 13 | .block_on(body) 14 | } 15 | #[rustc_main] 16 | #[coverage(off)] 17 | pub fn main() -> () { 18 | extern crate test; 19 | test::test_main_static(&[]) 20 | } 21 | -------------------------------------------------------------------------------- /rust-playground/t-protobuf/.gitignore: -------------------------------------------------------------------------------- 1 | /target 2 | /.idea 3 | -------------------------------------------------------------------------------- /rust-playground/t-protobuf/Cargo.toml: -------------------------------------------------------------------------------- 1 | [package] 2 | name = "t-protobuf" 3 | version = "0.1.0" 4 | edition = "2021" 5 | 6 | # See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html 7 | 8 | [dependencies] 9 | prost = "0.12.3" 10 | prost-types = "0.12.3" 11 | serde = { version = "1.0.195", features = ["derive"] } 12 | serde_json = "1.0.111" 13 | thiserror = "1.0.56" 14 | tokio = { version = "1.35.1", features = ["full"] } 15 | tonic = "0.10.2" 16 | 17 | 18 | [build-dependencies] 19 | prost-build = "0.12.3" 20 | tonic-build = "0.10.2" 21 | 22 | -------------------------------------------------------------------------------- /rust-playground/t-protobuf/build.rs: -------------------------------------------------------------------------------- 1 | // Copyright 2021 Datafuse Labs 2 | // 3 | // Licensed under the Apache License, Version 2.0 (the "License"); 4 | // you may not use this file except in compliance with the License. 5 | // You may obtain a copy of the License at 6 | // 7 | // http://www.apache.org/licenses/LICENSE-2.0 8 | // 9 | // Unless required by applicable law or agreed to in writing, software 10 | // distributed under the License is distributed on an "AS IS" BASIS, 11 | // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 | // See the License for the specific language governing permissions and 13 | // limitations under the License. 14 | 15 | // https://github.com/rust-lang/rustfmt/blob/e1ab878ccb24cda1b9e1c48865b375230385fede/build.rs 16 | 17 | use std::env; 18 | use std::path::Path; 19 | use std::path::PathBuf; 20 | 21 | fn main() { 22 | build_proto(); 23 | } 24 | 25 | fn build_proto() { 26 | let manifest_dir = 27 | env::var("CARGO_MANIFEST_DIR").expect("CARGO_MANIFEST_DIR env variable unset"); 28 | 29 | let proto_dir = Path::new(&manifest_dir).join("proto"); 30 | let protos = [ 31 | &Path::new(&proto_dir).join(Path::new("meta.proto")), 32 | // &Path::new(&proto_dir).join(Path::new("request.proto")), 33 | ]; 34 | 35 | for proto in protos.iter() { 36 | println!("cargo:rerun-if-changed={}", proto.to_str().unwrap()); 37 | } 38 | 39 | println!("cargo:rerun-if-changed=build.rs"); 40 | 41 | let mut config = prost_build::Config::new(); 42 | config.protoc_arg("--experimental_allow_proto3_optional"); 43 | 44 | let out_dir = PathBuf::from(env::var("OUT_DIR").unwrap()); 45 | tonic_build::configure() 46 | .file_descriptor_set_path(out_dir.join("meta_descriptor.bin")) 47 | // .type_attribute( 48 | // "SeqV", 49 | // "#[derive(Eq, serde::Serialize, serde::Deserialize)]", 50 | // ) 51 | // .type_attribute( 52 | // "TxnCondition.ConditionResult", 53 | // "#[derive(serde::Serialize, serde::Deserialize, num_derive::FromPrimitive)]", 54 | // ) 55 | // .type_attribute( 56 | // "TxnCondition.target", 57 | // "#[derive(Eq,serde::Serialize, serde::Deserialize)]", 58 | // ) 59 | // .type_attribute( 60 | // "TxnOp.request", 61 | // "#[derive(Eq,serde::Serialize, serde::Deserialize)]", 62 | // ) 63 | // .type_attribute( 64 | // "TxnOpResponse.response", 65 | // "#[derive(Eq, serde::Serialize, serde::Deserialize, derive_more::TryInto)]", 66 | // ) 67 | // .field_attribute( 68 | // "TxnPutRequest.ttl_ms", 69 | // r#"#[serde(skip_serializing_if = "Option::is_none")]"#, 70 | // ) 71 | .compile_with_config(config, &protos, &[&proto_dir]) 72 | .unwrap(); 73 | } 74 | -------------------------------------------------------------------------------- /rust-playground/t-protobuf/proto/meta.proto: -------------------------------------------------------------------------------- 1 | 2 | syntax = "proto3"; 3 | 4 | package meta; 5 | 6 | //import "request.proto"; 7 | 8 | message Foo { 9 | uint64 foo = 6; 10 | } 11 | 12 | message U64List { 13 | uint64 ver = 100; 14 | uint64 min_reader_ver = 101; 15 | 16 | 17 | repeated uint64 u64s = 1; 18 | } 19 | 20 | 21 | service MyService { 22 | rpc Handshake(stream Foo) returns (stream U64List); 23 | } -------------------------------------------------------------------------------- /rust-playground/t-protobuf/src/lib.rs: -------------------------------------------------------------------------------- 1 | #[allow(clippy::all)] 2 | pub mod protobuf { 3 | tonic::include_proto!("meta"); 4 | 5 | pub const FILE_DESCRIPTOR_SET: &[u8] = tonic::include_file_descriptor_set!("meta_descriptor"); 6 | } 7 | 8 | #[cfg(test)] 9 | mod tests { 10 | 11 | use crate::protobuf::{Foo, U64List}; 12 | #[test] 13 | fn test_foo() { 14 | let x = Foo { foo: 67 }; 15 | 16 | let mut buf = vec![]; 17 | prost::Message::encode(&x, &mut buf).unwrap(); 18 | println!("{:?}", buf); 19 | } 20 | } 21 | -------------------------------------------------------------------------------- /rust-playground/t-protobuf/src/main.rs: -------------------------------------------------------------------------------- 1 | fn main() { 2 | println!("Hello, world!"); 3 | } 4 | -------------------------------------------------------------------------------- /scripts/comments.html: -------------------------------------------------------------------------------- 1 | 9 | 24 | 55 | -------------------------------------------------------------------------------- /scripts/img-add-margin.sh: -------------------------------------------------------------------------------- 1 | #!/bin/sh 2 | 3 | # Add 50% margin to left and right side of an image 4 | # Usage: 5 | # $0 . [width] 6 | # output to: 7 | # -margin. 8 | # default width is 1600, while target width is 800 9 | 10 | fn="${1}" 11 | 12 | suffix="${fn##*.}" 13 | output_fn="${fn%.*}-margin.$suffix" 14 | 15 | width="${2-1600}" 16 | 17 | convert -resize 800 -gravity center -extent $width "$fn" "$output_fn" 18 | -------------------------------------------------------------------------------- /snippet/README.md: -------------------------------------------------------------------------------- 1 | Source code used by tips 2 | -------------------------------------------------------------------------------- /snippet/rust/dup-file/.gitignore: -------------------------------------------------------------------------------- 1 | /target 2 | /.idea 3 | 4 | Cargo.lock 5 | 6 | .DS_Store 7 | -------------------------------------------------------------------------------- /snippet/rust/dup-file/Cargo.toml: -------------------------------------------------------------------------------- 1 | [package] 2 | name = "dup-file" 3 | version = "0.1.0" 4 | edition = "2021" 5 | 6 | [dependencies] 7 | fs2 = "0.4.3" 8 | tempfile = "3.13.0" 9 | -------------------------------------------------------------------------------- /snippet/rust/dup-file/src/main.rs: -------------------------------------------------------------------------------- 1 | fn main() { 2 | println!("Hello, world!"); 3 | } 4 | -------------------------------------------------------------------------------- /snippet/rust/new-cargo: -------------------------------------------------------------------------------- 1 | #!/bin/sh 2 | 3 | cargo init $1 4 | 5 | cat >$1/.gitignore <<-END 6 | /target 7 | /.idea 8 | 9 | Cargo.lock 10 | 11 | .DS_Store 12 | END 13 | -------------------------------------------------------------------------------- /snippet/rust/pb-oneof-forward-compat/build.rs: -------------------------------------------------------------------------------- 1 | // Copyright 2023 Datafuse Labs. 2 | // 3 | // Licensed under the Apache License, Version 2.0 (the "License"); 4 | // you may not use this file except in compliance with the License. 5 | // You may obtain a copy of the License at 6 | // 7 | // http://www.apache.org/licenses/LICENSE-2.0 8 | // 9 | // Unless required by applicable law or agreed to in writing, software 10 | // distributed under the License is distributed on an "AS IS" BASIS, 11 | // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 | // See the License for the specific language governing permissions and 13 | // limitations under the License. 14 | 15 | -------------------------------------------------------------------------------- /snippet/rust/pb-oneof-forward-compat/proto/foo.proto: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/drmingdrmer/tips/047f274864fb33ac7f6da89eba8e806ac6edb49c/snippet/rust/pb-oneof-forward-compat/proto/foo.proto -------------------------------------------------------------------------------- /snippet/rust/serde-msgpack-bincode/.gitignore: -------------------------------------------------------------------------------- 1 | /target 2 | /.idea 3 | 4 | Cargo.lock 5 | 6 | .DS_Store 7 | -------------------------------------------------------------------------------- /snippet/rust/serde-msgpack-bincode/Cargo.toml: -------------------------------------------------------------------------------- 1 | [package] 2 | name = "serde-msgpack-bincode" 3 | version = "0.1.0" 4 | edition = "2021" 5 | 6 | [dependencies] 7 | bincode = "1.3.3" 8 | rmp-serde = "1.3.0" 9 | serde = { version = "1.0.214", features = ["derive"] } 10 | -------------------------------------------------------------------------------- /tips/Catalan number proof: generating function.md: -------------------------------------------------------------------------------- 1 | tags:: tips, math, math-combinatorics, proof 2 | 3 | [generating function](https://en.wikipedia.org/wiki/Generating_function) : 4 | 5 | $$ 6 | g(x) = \sum_{i=0}^{\infty} C_i x^i 7 | $$ 8 | 9 | From recurrence relation 10 | 11 | $$ 12 | C_{n+1} = \sum_{i=0}^{n} C_i C_{n-i} 13 | $$ 14 | 15 | We have: 16 | 17 | $$ 18 | g = 1 + x {g(x)}^2 19 | $$ 20 | 21 | 22 | Solve this quadratic equation of `c` it yields tow solution: 23 | 24 | $$ 25 | g(x) = \frac{1+\sqrt{1-4x}}{2x} 26 | \quad 27 | \text{or} 28 | \quad 29 | g(x) = \frac{1-\sqrt{1-4x}}{2x} 30 | $$ 31 | 32 | We choose the second one because it gives: $C_0 = \lim_{x \to 0} g(x) = 1$ 33 | 34 | The square root term is expanded as following, where $\frac{1}{2} \choose n$ is [Newton's generalized binomial theorem](https://en.wikipedia.org/wiki/Binomial_theorem#Newton's_generalized_binomial_theorem). 35 | 36 | $$ 37 | \sqrt{1+y} = 1 38 | +{\frac{1}{2} \choose 1} y 39 | +{\frac{1}{2} \choose 2} y^2 40 | +{\frac{1}{2} \choose 3} y^3 41 | +... 42 | $$ 43 | 44 | 45 | So we have: 46 | 47 | $$ 48 | \sqrt{1-4x} = \sum_{i=0}{\frac{1}{2} \choose i} (-1) ^ i 4^i x^i \tag{exp} 49 | $$ 50 | 51 | And we already know(where `!!` is [double factorial](https://en.wikipedia.org/wiki/Double_factorial)): 52 | 53 | $$ 54 | {\frac{1}{2} \choose i} = 55 | \frac{ 56 | \frac{1}{2} 57 | \frac{-1}{2} 58 | \frac{-3}{2} 59 | \frac{-5}{2} 60 | ... 61 | \frac{1-2i+2}{2} }{ i! } 62 | = 2^{-i} 63 | (-1)^{i+1} 64 | (2i-3)!! 65 | \frac{ 1 } { i! } 66 | \tag{gen-bin} 67 | $$ 68 | 69 | And we already know: 70 | 71 | $$ 72 | (2n)! = 2^n n! (2n-1)!! 73 | \tag{even-fac} 74 | $$ 75 | 76 | From (gen-bin) and (even-fac), we have: 77 | 78 | $$ 79 | {\frac{1}{2} \choose i} = 4^{-i} (-1)^{i+1} { 2i \choose i } \frac{1}{2i-1} 80 | \tag{gen-bin-2} 81 | $$ 82 | 83 | From (exp) and (gen-bin-2) we have: 84 | 85 | $$ 86 | \sqrt{1-4x} 87 | = - \sum_{i=0}\frac{1}{2i-1} { 2i \choose i} x^i 88 | \tag{sqrt-series} 89 | $$ 90 | 91 | 92 | Therefore, with (sqrt-series) we have: 93 | 94 | 95 | $$ 96 | g(x) = \frac{1-\sqrt{1-4x}}{2x} = \frac{1}{2} \sum_{i=1} \frac{1}{2i-1} {2i \choose i} x^{i-1} 97 | $$ 98 | 99 | Let j = i - 1: 100 | 101 | $$ 102 | g(x) = \sum_{j=0} \frac{1}{j+1} {2j \choose j} x^i 103 | $$ 104 | 105 | Finally, the coefficient of $x^i$: 106 | 107 | $$ 108 | C_n = \frac{1}{n+1} {2n \choose n} 109 | $$ 110 | -------------------------------------------------------------------------------- /tips/Catalan number 卡塔兰数.md: -------------------------------------------------------------------------------- 1 | tags:: tips, math, math-combinatorics 2 | 3 | [Catalan number](https://en.wikipedia.org/wiki/Catalan_number) satisfies **recurrence relation**: 4 | 5 | $$ 6 | C_0 = 1 7 | \quad 8 | \text{and} 9 | \quad 10 | C_{n+1} = \sum_{i=0}^{n} C_i C_{n-i} 11 | \tag{reccurrence} 12 | $$ 13 | 14 | And its general term formula is( ${2n \choose n}$ is [binomial-coefficient](https://en.wikipedia.org/wiki/Binomial_coefficient) ): 15 | 16 | $$ 17 | C_n = \frac{1}{n+1} {2n \choose n} 18 | $$ 19 | 20 | ## Proofs 21 | 22 | - [Catalan-number proof: generating function](./Catalan%20number%20proof:%20generating%20function.md) 23 | 24 | 25 | ## Application 26 | 27 | - The count of different [binary-tree](https://en.wikipedia.org/wiki/Binary_tree) of exactly `n` nodes is $C_n$: 28 | [n节点的binary-tree的个数](./n%20节点%20binary-tree%20的个数.md) 29 | 30 | -------------------------------------------------------------------------------- /tips/Chebyshev inequality 切比雪夫不等式.md: -------------------------------------------------------------------------------- 1 | tags:: tips, math, math-probability 2 | 3 | $$ 4 | P(|X - \mu| \ge b) \le \frac{Var(X)}{b^2} 5 | $$ 6 | 7 | where $\mu$ is the mean of `X`. 8 | 9 | ### Proof: 10 | 11 | Apply [[Markov inequality 马尔可夫不等式]] to the variables $Y=(X - \mu)^2$ 12 | 13 | $$ 14 | P(|X - \mu| \ge b) = P((X - \mu)^2 \ge b^2) \le \frac{E(X - \mu)^2}{b^2} = \frac{Var(X)}{b^2} 15 | $$ 16 | 17 | 18 | ### Applications: 19 | 20 | - $P(|X - \mu| \ge k \sigma ) \le \frac{1}{k^2}$ 21 | 22 | - 与平均相差2个标准差以上的值,数目不多于1/4 23 | - 与平均相差3个标准差以上的值,数目不多于1/9 24 | - ... 25 | 26 | 27 | - https://en.wikipedia.org/wiki/Chebyshev%27s_inequality 28 | -------------------------------------------------------------------------------- /tips/C语言宏实现循环.md: -------------------------------------------------------------------------------- 1 | tags:: tips, c-programming, macro, preprocessor, loop, for 2 | 3 | It is well explained in: 4 | https://github.com/swansontec/map-macro 5 | 6 | C 语言里如果需要对多个 error-code 实现类似的错误处理, 7 | 可以借助宏 [preprocessor](https://en.wikipedia.org/wiki/C_preprocessor) 8 | 来实现重复代码的生成. 9 | 10 | 虽然 C 语音的宏, 11 | 只提供了简单的判断和函数的语法, 如 12 | `#if VERBOSE >= 2`, 13 | `#define RADTODEG(x) ((x) * 57.29578)`, 14 | 没有类似 [Rust macro 的循环](https://doc.rust-lang.org/rust-by-example/macros/repeat.html) 支持, 15 | 我们也可以用递归的方式实现一个 [`for_each`](../c-playground/macro_for_each/macro_for_each.c) 的宏来生成重复代码. 16 | 17 | ```c 18 | // cat for_each.c: 19 | #include "for_each.h" 20 | #define handle_error(m) if (m == err) { \ 21 | log_error("error is: %s", #m); \ 22 | return -1; \ 23 | } 24 | 25 | for_each(handle_error, (a), (b), (c)); 26 | ``` 27 | 28 | 使用 `gcc -E macro_for_each.c` 展开宏后输出生成的代码: 29 | 30 | ```c 31 | if (a == err) { log_error("error is: %s", "a"); return -1; } 32 | if (b == err) { log_error("error is: %s", "b"); return -1; } 33 | if (c == err) { log_error("error is: %s", "c"); return -1; } 34 | ``` 35 | 36 | ```c 37 | // cat for_each.h 38 | #define EVAL(...) EVAL1(EVAL1(EVAL1(__VA_ARGS__))) 39 | #define EVAL1(...) EVAL2(EVAL2(EVAL2(__VA_ARGS__))) 40 | #define EVAL2(...) EVAL3(EVAL3(EVAL3(__VA_ARGS__))) 41 | #define EVAL3(...) EVAL4(EVAL4(EVAL4(__VA_ARGS__))) 42 | #define EVAL4(...) EVAL5(EVAL5(EVAL5(__VA_ARGS__))) 43 | #define EVAL5(...) __VA_ARGS__ 44 | 45 | #define arg1(a, ...) a 46 | #define shift(a, ...) __VA_ARGS__ 47 | 48 | #define __empty_ 1 49 | #define arg3(a1, a2, a3, ...) a3 50 | /* #define is_empty(ph, ...) arg3(ph, ##__VA_ARGS__, 1, 0) */ 51 | #define is_empty(ph, ...) ph, ##__VA_ARGS__, 1 52 | 53 | #define empty() 54 | #define defer(id) id empty() 55 | #define obstruct(...) __VA_ARGS__ defer(empty)() 56 | 57 | #define CAT(a, ...) PRIMITIVE_CAT(a, __VA_ARGS__) 58 | #define PRIMITIVE_CAT(a, ...) a ## __VA_ARGS__ 59 | 60 | #define COMPL(b) PRIMITIVE_CAT(COMPL_, b) 61 | #define COMPL_0 1 62 | #define COMPL_1 0 63 | 64 | #define IIF(cond) CAT(IIF_,cond) 65 | #define IIF_0(t, f) f 66 | #define IIF_1(t, f) t 67 | 68 | #define NOT(x) CHECK(PRIMITIVE_CAT(NOT_, x)) 69 | #define NOT_0 PROBE(~) 70 | 71 | #define BOOL(x) COMPL(NOT(x)) 72 | #define IF(c) IIF(BOOL(c)) 73 | 74 | #define CHECK_N(x, n, ...) n 75 | #define CHECK(...) CHECK_N(__VA_ARGS__, 0,) 76 | #define PROBE(x) x, 1, 77 | 78 | #define EAT(...) 79 | #define EXPAND(...) __VA_ARGS__ 80 | #define WHEN(c) IF(c)(EXPAND, EAT) 81 | 82 | #define IS_PAREN(x) CHECK(IS_PAREN_PROBE x) 83 | #define IS_PAREN_PROBE(...) PROBE(~) 84 | 85 | #define no_args_x(...) #__VA_ARGS__ 86 | #define no_args(...) 0 EVAL(no_args_(__VA_ARGS__, ())) 87 | 88 | #define no_args_(c, ...) \ 89 | IIF(BOOL(IS_PAREN(c)))( , \ 90 | + 1 \ 91 | obstruct(no_args_xx)()(__VA_ARGS__) \ 92 | ) 93 | 94 | #define no_args_xx() no_args_ 95 | 96 | #define for_each(statement, ...) EVAL(foreach(statement, __VA_ARGS__, ~)) 97 | 98 | #define foreach(statement, c, ...) \ 99 | IIF(BOOL(IS_PAREN(c)))( \ 100 | statement c \ 101 | obstruct(foreach_xx)()(statement, __VA_ARGS__) \ 102 | , \ 103 | ) 104 | 105 | #define foreach_xx() foreach 106 | ``` 107 | -------------------------------------------------------------------------------- /tips/Derangement 错排.md: -------------------------------------------------------------------------------- 1 | tags:: tips, math, math-combinatorics 2 | 3 | - https://zh.wikipedia.org/wiki/%E9%94%99%E6%8E%92%E9%97%AE%E9%A2%98 4 | - https://en.wikipedia.org/wiki/Derangement 5 | 6 | 设 $D_n$ 为 n 个数字不在自己位置上的排列总数. 7 | 8 | `D_2` = 1 9 | ``` 10 | 21 11 | ``` 12 | 13 | `D_3` = 2 14 | ``` 15 | 231 16 | 312 17 | ``` 18 | 19 | `D_4` = 9 20 | ``` 21 | 2143 -> 21.. 22 | 2341 -> 231. 23 | 2413 -> 231. 24 | 3142 -> 312. 25 | 3412 -> 3.1. 26 | 3421 -> 312. 27 | 4123 -> 312. 28 | 4312 -> 231. 29 | 4321 -> .32. 30 | ``` 31 | 32 | 一个错排将最后一个数字i与最大数字M交换: 33 | 34 | - (case-1) 对应一个$D_{n-1}$的错排(如果最大数字M不在位置i上) 35 | 36 | ``` 37 | num: ... M ... i 38 | index: i 39 | ``` 40 | 41 | - (case-2) 或者对应一个$D_{n-2}$的错排(如果最大数字M在位置i上) 42 | 43 | ``` 44 | num: ... M ... i 45 | index: i 46 | ``` 47 | 48 | ∴ $D_n = (n-1) D_{n-1} + (n-1) D_{n-2}$ 49 | 50 | 设 $F_n = D_n -nD_{n-1}$, 则 $F_n = -F_{n-1}$, 且$F_2 = 1$, 51 | 52 | ∴ $F_n = (-1)^n$ 53 | 54 | ∴ $D_n = n D_{n-1} + (-1)^n$ 55 | 56 | ∴ $D_n = n! \sum_{i=0}^n \frac{(-1)^i}{i!} \approx \frac{n!}{e}$ 57 | -------------------------------------------------------------------------------- /tips/Markov inequality 马尔可夫不等式.md: -------------------------------------------------------------------------------- 1 | tags:: tips, math, math-probability 2 | 3 | $$ 4 | P(X \ge a) \le \frac{E(X)}{a} 5 | $$ 6 | 7 | 8 | ### Proof: 9 | 10 | $$ 11 | a P(X \ge a) = \int_a^\infty a f(x) d x \le \int_a^\infty x f(x) d x \le \int_{- \infty}^\infty x f(x) d x = E(X) 12 | $$ 13 | 14 | - [马尔科夫不等式](https://zh.wikipedia.org/wiki/%E9%A6%AC%E7%88%BE%E5%8F%AF%E5%A4%AB%E4%B8%8D%E7%AD%89%E5%BC%8F) 15 | 16 | -------------------------------------------------------------------------------- /tips/Probability basic.md: -------------------------------------------------------------------------------- 1 | tags:: tips, math, math-probability 2 | 3 | - $f(x)$, 概率密度函数 4 | - $F(x)$, 概率累计函数 5 | 6 | - $\mu$, mean, 均值 7 | 8 | - $\mu$, 9 | - $E(X)$, 10 | - $\int f(x) dx$ 11 | 12 | - $\sigma^2$, variance, 方差 13 | 14 | - $\sigma^2$, 15 | - $Var(X)$, 16 | - $E[(X - u)^2] = E[ X^2 ] - E[ X ]^2$, 17 | - $\int (x-u)^2 f(x) dx = \int x^2 f(x) dx - u^2$, 18 | - [方差](https://zh.wikipedia.org/wiki/%E6%96%B9%E5%B7%AE) 19 | 20 | - $\sigma$, standard deviation, SD, 标准差, 均方差 21 | 22 | - [标准差](https://zh.wikipedia.org/wiki/%E6%A8%99%E6%BA%96%E5%B7%AE) 23 | -------------------------------------------------------------------------------- /tips/Rust Cargo dependency 分类.md: -------------------------------------------------------------------------------- 1 | tags:: tips, rust-programming, cargo, dep 2 | 3 | `Cargo.toml` dependency 按照类别来管理, 以下是我自己建立的一些常用类别: 4 | 5 | ```toml 6 | # data flow 7 | futures = { workspace = true } 8 | itertools = { workspace = true } 9 | 10 | # data structure 11 | binary-heap-plus= { workspace = true } 12 | lru-cache = { workspace = true } 13 | compare = { workspace = true } 14 | 15 | # error handling 16 | anyhow = { workspace = true } 17 | 18 | # serialization 19 | byteorder = { workspace = true } 20 | bytes = { workspace = true } 21 | crc32fast = { workspace = true } 22 | serde = { workspace = true } 23 | serde_json = { workspace = true } 24 | 25 | # testing 26 | maplit = { workspace = true } 27 | tempfile = { workspace = true } 28 | ``` 29 | -------------------------------------------------------------------------------- /tips/Rust branchless bsearch.md: -------------------------------------------------------------------------------- 1 | tags:: tips, rust-programming, search, branchless 2 | 3 | [bsearch-branchless.rs](../rust-playground/src/bin/bsearch-branchless.rs) 4 | 5 | ```rust 6 | fn bsearch(elts: &[T], v: &T) -> usize { 7 | let mut lr = [0, elts.len()]; 8 | 9 | while lr[0] + 1 < lr[1] { 10 | let mid = (lr[0] + lr[1]) / 2; 11 | lr[(v < &elts[mid]) as usize] = mid; 12 | } 13 | lr[0] 14 | } 15 | ``` 16 | 17 | 测试一下: 18 | 19 | ```rust 20 | fn main() { 21 | let a: Vec = vec![1, 2, 5, 7, 8]; 22 | 23 | for v in [0, 1, 2, 3, 4, 5, 6, 7, 8, 9] { 24 | let index = bsearch(&a, &v); 25 | println!("bsearch({:?}, {}) -> {}", a, v, index); 26 | } 27 | } 28 | // bsearch([1, 2, 5, 7, 8], 0) -> 0 29 | // bsearch([1, 2, 5, 7, 8], 1) -> 0 30 | // bsearch([1, 2, 5, 7, 8], 2) -> 1 31 | // bsearch([1, 2, 5, 7, 8], 3) -> 1 32 | // bsearch([1, 2, 5, 7, 8], 4) -> 1 33 | // bsearch([1, 2, 5, 7, 8], 5) -> 2 34 | // bsearch([1, 2, 5, 7, 8], 6) -> 2 35 | // bsearch([1, 2, 5, 7, 8], 7) -> 3 36 | // bsearch([1, 2, 5, 7, 8], 8) -> 4 37 | // bsearch([1, 2, 5, 7, 8], 9) -> 4 38 | ``` 39 | -------------------------------------------------------------------------------- /tips/Rust branchless heap sort.md: -------------------------------------------------------------------------------- 1 | tags:: tips, rust-programming, sort, branchless 2 | 3 | https://github.com/rust-lang/rust/pull/107894 4 | 5 | 3个版本的汇编代码对比, 后2种少一个分支: 6 | 7 | - Original https://godbolt.org/z/M9zrMWbW1 8 | - Combined cond https://godbolt.org/z/7Es3avoYn 9 | - Split cond https://godbolt.org/z/nhxoKcW3z 10 | 11 | - Diff Asm of the last two: https://godbolt.org/z/arcsxcEc5 12 | 13 | 优化点: 14 | 15 | - `child + 1 < v.len()` 是一个非常可预期的判断, 大部分情况为 `true`; 16 | - `is_less()` 不可预期, 会造成比较多的分支预测失效, 所以这里把它优化成整数操作. 17 | 18 | 19 | 最快的是这样, 1个分支加一个整数运算: 20 | 21 | ```rust 22 | if child + 1 < v.len() { 23 | // We need a branch to be sure not to out-of-bounds index, 24 | // but it's highly predictable. The comparison, however, 25 | // is better done branchless, especially for primitives. 26 | child += is_less(&v[child], &v[child + 1]) as usize; 27 | } 28 | // lea rcx, [rax + 2] 29 | // cmp rcx, rsi 30 | // jae .LBB0_5 31 | // mov rcx, qword ptr [rdi + 8*rdx] 32 | // cmp rcx, qword ptr [rdi + 8*rax + 16] 33 | // adc rdx, 0 34 | ``` 35 | 36 | 但是似乎强制都写成整数运算也还会留下一个branch: 37 | https://godbolt.org/z/xrYPKfxjo 38 | 39 | ```rust 40 | child += ((child + 1 < v.len()) as usize) & (is_less(&v[child], &v[child + 1]) as usize); 41 | // lea rcx, [rax + 2] 42 | // cmp rcx, rsi 43 | // jae .LBB0_21 44 | // mov rcx, qword ptr [rdi + 8*rdx] 45 | // cmp rcx, qword ptr [rdi + 8*rax + 16] 46 | // mov rcx, rdx 47 | // adc rcx, 0 48 | ``` 49 | 50 | ```rust 51 | pub fn heapsort(v: &mut [T], mut is_less: F) 52 | where 53 | F: FnMut(&T, &T) -> bool, 54 | { 55 | // This binary heap respects the invariant `parent >= child`. 56 | let mut sift_down = |v: &mut [T], mut node| { 57 | loop { 58 | // Children of `node`. 59 | let mut child = 2 * node + 1; 60 | if child >= v.len() { 61 | break; 62 | } 63 | 64 | // Before optimization: 65 | // if (child + 1 < v.len() && is_less(&v[child], &v[child + 1])) { 66 | // child += 1; 67 | // } 68 | 69 | // Choose the greater child. 70 | if child + 1 < v.len() { 71 | // We need a branch to be sure not to out-of-bounds index, 72 | // but it's highly predictable. The comparison, however, 73 | // is better done branchless, especially for primitives. 74 | child += is_less(&v[child], &v[child + 1]) as usize; 75 | } 76 | 77 | // Stop if the invariant holds at `node`. 78 | if !is_less(&v[node], &v[child]) { 79 | break; 80 | } 81 | 82 | // Swap `node` with the greater child, move one step down, and continue sifting. 83 | v.swap(node, child); 84 | node = child; 85 | } 86 | }; 87 | 88 | // Build the heap in linear time. 89 | for i in (0..v.len() / 2).rev() { 90 | sift_down(v, i); 91 | } 92 | 93 | // Pop maximal elements from the heap. 94 | for i in (1..v.len()).rev() { 95 | v.swap(0, i); 96 | sift_down(&mut v[..i], 0); 97 | } 98 | } 99 | 100 | pub fn x(v: &mut [u64]) { 101 | heapsort(v, |a, b| a.lt(b)); 102 | } 103 | ``` 104 | -------------------------------------------------------------------------------- /tips/Rust bug.md: -------------------------------------------------------------------------------- 1 | tags:: tips, rust-programming, bug, issue 2 | 3 | 目前 Rust 语言中遇到的bug: 4 | 5 | 对我项目影响较大的已经归到这个 github project: 6 | [Rust bugs that bother xp!](https://github.com/users/drmingdrmer/projects/2) 7 | 8 | - [ ] incorrect lifetime bound errors when asserting Send for a Future: 9 | 10 | Tags: async, lifetime, generator, generic-associated-type, 11 | 12 | Repro: [bug-send-higher-ranked-lifetime.rs](../rust-playground/src/bin/bug-send-higher-ranked-lifetime.rs) 13 | 14 | 15 | 相关issue: 16 | 17 | Unexpected higher-ranked lifetime error in GAT usage #100013 18 | https://github.com/rust-lang/rust/issues/100013 19 | 20 | 这个issue中提到的另一个repro: 21 | 22 | ```rust 23 | #![feature(generic_associated_types)] 24 | 25 | pub trait FutureIterator { 26 | type Future<'s, 'cx>: Send 27 | where 's: 'cx; 28 | } 29 | 30 | fn call_2() -> impl Send { 31 | async { // a generator checked for autotrait impl `Send` 32 | let x = None::>; // a type referencing GAT 33 | async {}.await; // a yield point 34 | } 35 | } 36 | ``` 37 | 38 | Higher ranked lifetime error when tryng to see that a future is send. #114046 39 | https://github.com/rust-lang/rust/issues/114046 40 | 41 | Tracking issue for incorrect lifetime bound errors in async #110338 42 | https://github.com/rust-lang/rust/issues/110338 43 | 44 | Lifetime bounds in auto trait impls prevent trait from being implemented on generators #64552 45 | https://github.com/rust-lang/rust/issues/64552 46 | 47 | 48 | -------------------------------------------------------------------------------- /tips/Rust detect nightly.md: -------------------------------------------------------------------------------- 1 | tags:: tips, rust-programming, toolchaine, nightly, stable 2 | 3 | 使用 `rustc --version` 4 | ```rust 5 | // build.rs 6 | fn main() { 7 | // Copied from anyhow 8 | let rustc = env::var_os("RUSTC").unwrap(); 9 | let output = Command::new(rustc).arg("--version").output().unwrap(); 10 | let version = str::from_utf8(&output.stdout).unwrap(); 11 | let is_nightly = version.contains("nightly") || version.contains("dev") 12 | if is_nightly { 13 | println!("cargo:rustc-cfg=rustc_nightly"); 14 | } 15 | } 16 | 17 | // main.rs 18 | fn main() { 19 | #[cfg(rustc_nightly)] 20 | println!("rustc_nightly"); 21 | } 22 | ``` 23 | 24 | 使用环境变量 `RUSTUP_TOOLCHAIN` 25 | ```rust 26 | // build.rs 27 | fn main() { 28 | // With RUSTUP_TOOLCHAIN 29 | // https://stackoverflow.com/questions/59542378/conditional-compilation-for-nightly-vs-stable-rust-or-compiler-version 30 | let rust_toolchain = env::var("RUSTUP_TOOLCHAIN").unwrap(); 31 | if rust_toolchain.starts_with("stable") { 32 | // do nothing 33 | } else if rust_toolchain.starts_with("nightly") { 34 | //enable the 'nightly-features' feature flag 35 | println!("cargo:rustc-cfg=feature=\"env_nightly\""); 36 | } else { 37 | panic!("Unexpected value for rustc toolchain") 38 | } 39 | } 40 | 41 | // main.rs 42 | fn main() { 43 | #[cfg(feature = "env_nightly")] 44 | println!("env_nightly"); 45 | } 46 | ``` 47 | 48 | 49 | Code: [detect-nightly](../rust-playground/t-detect-nightly) 50 | -------------------------------------------------------------------------------- /tips/Rust ref vs ref-keyword.md: -------------------------------------------------------------------------------- 1 | tags:: tips, rust-programming, ref, rust-borrow, pattern 2 | 3 | 在 Rust 的 pattern match 中, 使用`ref` 来创建引用, 可以减小引用的 scope, 4 | 从而解决一些直接使用`& foo` 无法解决的问题, 例如 `can not borrow mutable twice` 的问题. 5 | 6 | 这是因为 `match &foo {...}` 或 `if let Some(x) = &foo {}` 的语句中, `&foo` 7 | 的引用一直被持有直到 `match` 或 `if` 结束. 8 | 9 | 看代码: 10 | 11 | ```rust 12 | struct Foo { 13 | writer: Option, 14 | } 15 | 16 | impl Foo { 17 | fn ref_keyword_is_ok(&mut self) -> &mut u64 { 18 | if let Some(ref mut w) = self.writer { // 19 | w // Scope of `&mut self.writer` ends here 20 | } else { // 21 | self.writer.insert(5) // 22 | } // 23 | } 24 | 25 | fn as_mut_does_not_compile(&mut self) -> &mut u64 { 26 | if let Some(w) = self.writer.as_mut() { // 27 | w // 28 | } else { // 29 | self.writer.insert(5) // 30 | } // Scope of `&mut self.writer` lasts as long as the if-let statement, 31 | // and ends here 32 | } 33 | } 34 | 35 | fn main() {} 36 | ``` 37 | 38 | ``` 39 | error[E0499]: cannot borrow `self.writer` as mutable more than once at a time 40 | | 41 | 15 | async fn maybe_init_writer_that_does_not_compile(&mut self) -> &mut u64 { 42 | | ______________________________________________________-______________________- 43 | | | | 44 | | | let's call the lifetime of this reference `'1` 45 | 16 | | if let Some(writer) = self.writer.as_mut() { 46 | | | -------------------- first mutable borrow occurs here 47 | 17 | | writer 48 | 18 | | } else { 49 | 19 | | self.writer.insert(5) 50 | | | ^^^^^^^^^^^^^^^^^^^^^ second mutable borrow occurs here 51 | 20 | | } 52 | 21 | | } 53 | | |_____- returning this value requires that `self.writer` is borrowed for `'1` 54 | ``` 55 | -------------------------------------------------------------------------------- /tips/Rust unstable min_specialization.md: -------------------------------------------------------------------------------- 1 | tags:: tips, rust-programming, unstable, trait, min_specialization 2 | 3 | 启用 `min_specialization` 之后, 可以为 trait 提供一个默认(default)实现, 然后为多个特定 type 提供特化(specialized)实现. 4 | 当 trait 被特定 type 实例化时, specialized 实现将优先于 default 实现, 允许更精确地控制 type 的行为. 5 | 这种方法在需要根据不同 type 特性来调整代码逻辑时非常有用. 6 | 7 | 例子: 8 | 定义一个名为 `Trait` 的 trait , 并为任意 type `T` 提供一个 **default** 实现; 9 | 接下来, 为`u64` type 提供了一个 **speicliazed** 的实现. 它不会影响 `T` 的默认实现. 10 | 11 | ```rust 12 | trait Trait { 13 | fn desc(&self) -> String; 14 | } 15 | 16 | /* default impl */ 17 | impl Trait for T { 18 | default fn desc(&self) -> String { 19 | "something".to_string() 20 | } 21 | } 22 | 23 | /* specialized impl */ 24 | impl Trait for u64 { 25 | fn desc(&self) -> String { 26 | format!("{}", self) 27 | } 28 | } 29 | 30 | fn main() { 31 | println!("{}", 1u16.desc()); // "something" 32 | println!("{}", 1u32.desc()); // "something" 33 | println!("{}", 1u64.desc()); // "1" 34 | } 35 | ``` 36 | 37 | - [min-specialization.rs](../rust-playground/src/bin/min-specialization.rs) 38 | - [specialization.rs](../rust-playground/src/bin/specialization.rs) 39 | -------------------------------------------------------------------------------- /tips/Rust 中 trait 的 lifetime 使用示例.md: -------------------------------------------------------------------------------- 1 | tags:: tips, rust-programming, trait, rust-lifetime 2 | 3 | Rust 中 trait 和 lifetime 结合使用会让编程变得复杂. 4 | 因为多个trait 对多个 struct 的实现之间会产生 lifetime 参数的影响. 5 | 例如某个 trait 的定义可以实现给A, B两个struct, 但再实现给C就会报错. 6 | 7 | 举个例子, 假设我们要设计一个简单的KV接口的MapApi: 8 | 9 | 10 | - [map-api-simplified.rs](../rust-playground/src/bin/map-api-simplified.rs) 11 | 12 | 我们给出一个不含有 lifetime 参数简化版的设计, 13 | 及实现了Level, Writable, StaticLevels, RefMut 这4个 struct, 14 | 用来展示功能. 15 | 16 | 这个版本的map trait实现给'static 类型的数据, 每个trait method 接受一个引用. 17 | 所以这个map trait 无法为一个临时变量实现, 例如下面的代码中, 18 | tmp是一个临时变量, 则MapApi::get(&self) 在这个场合就无法使用了. 19 | 20 | ```rust 21 | fn foo() -> () { 22 | let tmp = Tmp::new(); 23 | tmp.get("key").await 24 | } 25 | ``` 26 | 27 | - [map-api-lifetime.rs](../rust-playground/src/bin/map-api-lifetime.rs) 28 | 29 | 然后给出一个带 lifetime 参数的trait设计也实现了以上4个 struct, 30 | 用来展示复杂的 lifetime trait 如何使用, 31 | 这个例子里 trait 设计为可以实现给非 `'static` 的对象使用, 提供了更多灵活性, 32 | 但也给 `trait` 设计带来的挑战. 33 | 在这个实现中有2个重要的 `lifetime` 参数为 `'me` 和 `'d`, 34 | 用于描述 Self 的 lifetime 和它引用(或持有)的数据的 lifetime; 35 | 例如`&'me mut RefMut<'d> { data: &'d mut Level }` 中 Self 就允许有不同的 lifetime: 36 | 37 | 38 | 另外2个例子展示了不当的设计产生的问题: 39 | 40 | - [map-api-error-map-api-need-2-param.rs](../rust-playground/src/bin/map-api-error-map-api-need-2-param.rs) 41 | 42 | MapApi 需要 2个 lifetime 参数: `'me` 和 `'d`, 43 | 用于描述 Self 的 lifetime 和它引用(或持有)的数据的 lifetime; 44 | 例如`&'me 'mut RefMut<'d> { data: &'d mut Level }`, 虽然大部分时候, `'me` 和 `'d` 是一样的, 这个例子展示了为何必须区分这2个 lifetime: 45 | `Error: cannot infer an appropriate lifetime for lifetime parameter `'d` due to conflicting requirements`: 46 | 47 | - [map-api-error-2-lifetime.rs](../rust-playground/src/bin/map-api-error-2-lifetime.rs) 48 | 49 | `async move {}` block 生成的 Future 中如果 ref 了其他数据, 50 | 这个 Future 则包含一个 lifetime, 如果 ref 了多个数据, 会产生 `lifetime used multiple times` 的错误 51 | 52 | ``` 53 | note: lifetime used multiple times 54 | --> src/bin/map-api-error-2-lifetime.rs:175:6 55 | | 56 | 175 | impl<'me, 'd, K> MapApiRO<'d, K> for &'me Writable<'d> 57 | | ^^^^^^ ^^^^^ 58 | ``` 59 | 60 | 解决方法是把多个 ref 的 lifetime 归到一个新的lifetime参数`'f` 上: 61 | 62 | ```rust 63 | impl<'me, 'd, K> MapApiRO<'d, K> for &'me Writable<'d> 64 | where 65 | K: MapKey, 66 | for<'him> &'him Level: MapApiRO<'him, K>, 67 | { 68 | type GetFut<'f, Q> = impl Future + 'f 69 | where Self: 'f, 70 | 'me: 'f, 71 | 'd: 'f, 72 | K: Borrow, 73 | Q: Ord + Send + Sync + ?Sized, 74 | Q: 'f; 75 | 76 | fn get<'f, Q>(self, key: &'f Q) -> Self::GetFut<'f, Q> 77 | where 78 | 'me: 'f, 79 | 'd: 'f, 80 | K: Borrow, 81 | Q: Ord + Send + Sync + ?Sized, 82 | { 83 | async move { 84 | let level_data = &*self.writable; 85 | let got = level_data.get(key).await; 86 | got 87 | } 88 | } 89 | } 90 | ``` 91 | 92 | TODO: 或者为GAT配置多个lifetime参数? 93 | 94 | 95 | 96 | -------------------------------------------------------------------------------- /tips/Rust 中使用 attribute 定义的 thread_local 的 drop 方法不被调用.md: -------------------------------------------------------------------------------- 1 | tags:: tips, rust-programming, thread-local, drop, trap 2 | 3 | 4 | Rust 中有2种方法声明 [thread-local](https://en.wikipedia.org/wiki/Thread-local_storage) 变量: 使用标准库的宏 [`thread_local!{}`](https://doc.rust-lang.org/std/macro.thread_local.html) 或使用 attribute [`#[thread_local]`](https://doc.rust-lang.org/beta/unstable-book/language-features/thread-local.html), 这里有个不**rust**的地方, `#[thread_local]` 按官方说法是被"translates directly to the `thread_local` attribute in LLVM", 线程销毁时不会调用它的`drop`方法, 但宏声明的thread-local变量没问题: 5 | 6 | **使用宏 `thread_local!{...}` 定义, 正常调用了 `drop`**: 7 | 8 | [Online Playground](https://play.rust-lang.org/?version=nightly&mode=debug&edition=2021&gist=998357c6308a37ea4a53300843d38fae) 9 | 10 | [thread_local_macro_drop.rs](../rust-playground/src/bin/thread_local_macro_drop.rs) 11 | 12 | ```rust 13 | struct Foo(usize); 14 | impl Drop for Foo { 15 | fn drop(&mut self) { println!("dropped"); } 16 | } 17 | 18 | thread_local! { 19 | static MACRO_TLS: std::cell::RefCell = std::cell::RefCell::new(Foo(0)); 20 | } 21 | 22 | fn main() { 23 | let _ = std::thread::spawn(|| unsafe { 24 | MACRO_TLS.with(|f| { 25 | println!("foo: {}", f.borrow_mut().0); 26 | }); 27 | }) 28 | .join(); 29 | } 30 | // Output: 31 | // foo: 0 32 | // dropped 33 | ``` 34 | 35 | **使用 attribute `#[thread_local]` 定义, 没有调用 `drop`**: 36 | 37 | [Online Playground](https://play.rust-lang.org/?version=nightly&mode=debug&edition=2021&gist=a419e002b5b8d462dde9ceea93dc6e7f) 38 | 39 | [thread_local_attr_not_dropped.rs](../rust-playground/src/bin/thread_local_attr_not_dropped.rs) 40 | 41 | ```rust 42 | #![feature(thread_local)] 43 | struct Foo(usize); 44 | impl Drop for Foo { 45 | fn drop(&mut self) { println!("dropped"); } 46 | } 47 | 48 | #[thread_local] 49 | static mut ATTR_TLS: Foo = Foo(0); 50 | 51 | fn main() { 52 | let _ = std::thread::spawn(|| unsafe { 53 | println!("foo: {}", ATTR_TLS.0); 54 | }) 55 | .join(); 56 | } 57 | // Output: 58 | // foo: 0 59 | ``` 60 | -------------------------------------------------------------------------------- /tips/Rust 中对enum size的优化.md: -------------------------------------------------------------------------------- 1 | tags:: tips, rust-programming, enum, memory, null-pointer 2 | 3 | `enum` 的内存大小一般是它最大的 variant 的大小, 加上一个 `tag` 的大小, 4 | tag 是 enum 内部用于区分当前是哪个 variant. 因为 tag 需要参与计算 enum 的内存对齐, 5 | 所以如果 enum 中最大的 variant 是一个 8 bytes 的指针, 那么它的大小理论上是对齐到 8 bytes 的 tag 加 6 | 8 bytes 的指针, 共16 bytes: 7 | 8 | ```rust 9 | // 8 bytes pointer 10 | Arc1(Arc) 11 | 12 | // 16 bytes = 8 bytes tag + union of two 8 bytes pointers 13 | // 14 | // memory layout: [8 bytes tag][union [8 bytes pointer], 15 | // [8 bytes pointer]] 16 | enum Arc_Arc { 17 | Arc1(Arc), 18 | Arc2(Arc), 19 | } 20 | ``` 21 | 22 | 在实现上, Rust 会为特殊的 variant 类型做优化以减少 tag 的空间开销, 23 | 如果: 24 | - enum 只有2个 variant; 25 | - 其中一个 variant 在某段内存上一定**非0**, 26 | - 另一个 variant 在同样一段内存上一定**是0**, 27 | 28 | 那么 Rust 就不会为这个 enum 添加tag, 29 | 而直接使用这段内存 **是否是0** 来判断 enum 当前是哪个variant. 30 | 31 | 例如, `Arc` 是 8 bytes 的非空指针, 因为 `Blank` 不包含数据, 可以认为是全0的值, 32 | 所以下面这个 enum 不需要 tag: 33 | 34 | ```rust 35 | // size: 8; without tag 36 | enum Blank_Arc { 37 | Blank, 38 | Arc(Arc), 39 | } 40 | ``` 41 | 42 | 再如, `Arc` 是1个 8 bytes 指针, `Arc` 是2个 8 bytes 指针(data 43 | pointer和vtable pointer), 44 | 在它们2个的内存布局上有一个 8 bytes 分别是全0和非全0的. 所以这样一个 enum 45 | 也不需要 tag: 46 | 47 | ```rust 48 | // size: 16; without tag 49 | enum Arc_ArcDyn { 50 | Arc(Arc), 51 | ArcDyn(Arc), 52 | } 53 | ``` 54 | 55 | 第3个例子, 使用某段没被使用的 bits 作为 niche, 作为 enum 的 tag. 56 | 57 | ```rust 58 | // 8 bytes 59 | struct WithNiche { 60 | fill1: u32, 61 | fill2: u16, 62 | fill3: u8, 63 | niche: bool, 64 | } 65 | 66 | // 8 bytes, using the value 2-255 in the last byte in `WithNiche` as tag. 67 | enum Enum { 68 | NicheContainingVariant(WithNiche), 69 | B4bytes(u32), 70 | C4bytes(f32), 71 | D6bytes([u16;3]), 72 | } 73 | ``` 74 | 75 | 演示代码见: 76 | [enum-size.rs](../rust-playground/src/bin/enum-size.rs) 77 | -------------------------------------------------------------------------------- /tips/Rust 中引用旧版本的代码.md: -------------------------------------------------------------------------------- 1 | tags:: tips, rust-programming, cargo 2 | 3 | 软件有升级时, 需要提供一个升级程序, 读旧数据, 转换, 写入新格式的数据. 4 | 所以要求它的代码中同时使用新旧两个版本的代码, 5 | Cargo.toml 提供了方便的方法允许 main branch 中可以直接引用 `0.8.176` 版本中的数据定义: 6 | 其中, `git` 指定代码库的 url, 7 | `tag` 指定引用哪个版本, 8 | `package` 用于指定引用这个 repo 中的哪个 crate. 9 | 10 | #### Branch `main` 11 | 12 | ```text 13 | # cat Cargo.toml 14 | [dependencies] 15 | ... 16 | meta-app-v1 = { 17 | git = "https://github.com/datafuselabs/databend", # -. 18 | tag = "v0.8.176", # | 19 | package = "common-meta-app" # --------------. | 20 | } | | 21 | | | 22 | | | 23 | # cat src/lib.rs | | 24 | ... | | 25 | use meta_app_v1::schema::TableMeta; // ----. | | 26 | | | | 27 | ``` 28 | 29 | #### Tag `v0.8.176` 30 | 31 | ```text 32 | | | | 33 | ./databend/ <------------------------------|----|--------' 34 | ... | | 35 | ▾ src/ | | 36 | ▾ meta/ | | 37 | ▾ app/ | | 38 | ▾ src/ | | 39 | ▾ schema/ | | 40 | mod.rs | | 41 | table.rs | | 42 | # pub struct TableIdent { <-' | 43 | # pub table_id: u64, | 44 | # } | 45 | lib.rs | 46 | Cargo.toml | 47 | # [package] | 48 | # name = "common-meta-app" <----------' 49 | # ... 50 | ``` 51 | 52 | -------------------------------------------------------------------------------- /tips/Rust 中每个 match 分支都占用栈上空间.md: -------------------------------------------------------------------------------- 1 | tags:: tips, rust-programming, stack, match, overflow 2 | 3 | [match-arm-stack-size.rs](../rust-playground/src/bin/match-arm-stack-size.rs) 4 | 5 | Rust 中 match 的每个分支都会被分配一块 stack 上的内存, 并且这些内存不是公用的, 6 | 也就是说,如果 `outer` 函数里面有多个 `match` 的分支,并且每个分支都会分配一些栈上内存的话, 7 | 那 outer 调用的另一个 inner 函数的栈空间就会排在所有这些被占用的内存之后。 8 | 9 | 所以当这种分配了较多内存的 match 分支的函数被调用很多层之后,就非常容易出现栈溢出。 10 | 11 | 解决方法是把 match arm 放到另一个函数里. 12 | 13 | ```rust 14 | static mut RSP: isize = 0; 15 | 16 | fn main() { 17 | print_stack_pos("main"); 18 | outer(); 19 | } 20 | 21 | fn outer() { 22 | let v = 0; 23 | match v { 24 | _ if v == 0 => inner(), 25 | _ if v == 1 => [0u8; 1024][0], 26 | _ if v == 2 => [0u8; 1024 * 2][0], 27 | _ => 0, 28 | }; 29 | } 30 | 31 | fn inner() -> u8 { 32 | print_stack_pos("inner"); 33 | 0 34 | } 35 | 36 | fn print_stack_pos(msg: impl Display) { 37 | let a = (); 38 | let ptr = &a as *const _ as isize; 39 | 40 | let prev = unsafe { RSP }; 41 | println!("{:>5} stack ptr: {:x}, diff: {}", msg, ptr, prev - ptr); 42 | unsafe { RSP = ptr; } 43 | } 44 | ``` 45 | 46 | 上面的代码会打印出调用链 `main() -> outer() -> inner()` 过程中 `main()` 和 `inner()` 的栈位置相差大约3KB, 47 | 因为outer() 的 match 分支 **一共** 分配了3KB内存. 48 | 49 | ``` 50 | main stack ptr: 16fd61ff7, diff: -6171271159 51 | inner stack ptr: 16fd613b7, diff: 3136 52 | ``` 53 | 54 | 不管是函数还是 block 都提供了一个作用域,但是函数作用域会改变 stack 顶的位置,而 block 的作用域不会改变 stack 顶的位置,所有的变量在 stack 上的位置是在进入函数时就已经分配好的, 不论是否会被使用. 55 | 例如如下代码 `inner()` 也会打出3KB大小的 stack 位置变化. 56 | 57 | ```rust 58 | fn outer_blocks() { 59 | { inner(); } 60 | { let _c = [0u8; 1024]; } 61 | { let _c = [0u8; 1024 * 2]; } 62 | } 63 | ``` 64 | -------------------------------------------------------------------------------- /tips/Rust 从 mut ref 得到 ref 需要额外的 lifetime 限制.md: -------------------------------------------------------------------------------- 1 | tags:: tips, rust-programming, rust-lifetime, rust-borrow, mutable, reference 2 | 3 | 以前用过的所有语言, 脑子里有个大致思路后开始码, 最后肯定能把思路码出来不会出现意外. 4 | 但写Rust后经常遇到某个符合(粗糙的)直觉的思路在Rust里无法实现的情况... 5 | 6 | [mut-ref-to-ref.rs](../rust-playground/src/bin/mut-ref-to-ref-require-lifetime-constraint.rs) 7 | 8 | 例如下面的代码中, 9 | 想分别从结构体 Ref 和 RefMut 中拿出 `&T`, 10 | 遇到了 `&T` 和 `&mut T` 对生命周期的要求不一样的问题: 11 | `RefMut::get_data()` 额外要求 `'me: 't` 12 | 13 | 因为 `&mut T` 不是 `Copy` 的, 14 | 要使用 `&T` 就必须保证这期间 `&'me self` 不被 `drop`, 15 | 否则会导致 `&'t mut T` 在 `'t` 的生命周期内有第2个引用而破坏借用原则. 16 | 17 | ```rust 18 | struct Ref<'t> { data: &'t () } 19 | struct RefMut<'t> { data: &'t mut () } 20 | 21 | impl<'t> Ref<'t> { 22 | fn get<'me>(&'me self) -> &'t () { self.data } 23 | } 24 | 25 | impl<'t> RefMut<'t> { 26 | // Without `where 'me: 't`: 27 | // | self.data 28 | // | ^^^^^^^^^ associated function was supposed 29 | // | to return data with lifetime `'t` 30 | // | but it is returning data with lifetime `'me` 31 | fn get<'me>(&'me mut self) -> &'t () { self.data } 32 | } 33 | ``` 34 | -------------------------------------------------------------------------------- /tips/Rust 使用Fn作为泛型无法约束lifetime.md: -------------------------------------------------------------------------------- 1 | tags:: tips, rust-programming, generic, rust-lifetime 2 | 3 | Rust 中如果一个 struct 有一个泛型参数为 Fn 类型, 且这个 Fn 也返回一个泛型类型, 4 | 且跟Fn的参数有 lifetime 的约数, 那么是无法编译成功的. 5 | 个人对这个问题的理解是, 泛型定义(where)中, 无法把2个泛型参数使用 lifetime 6 | 关联起来; 而当这些泛型实例化时, 将实例类型填回泛型参数生成实际编译的代码后, 7 | 用lifetime约束再去检查时就会出现问题: 本该是互相约束的lifetime(Fut的和F的), 8 | 变成了不同的lifetime. 9 | 10 | [fail.rs](../rust-playground/src/bin/async-fn-as-generic.rs) 11 | 12 | ```rust 13 | use std::future::Future; 14 | 15 | struct Foo 16 | where 17 | Fut: Future, 18 | F: for<'a> Fn(&'a u64) -> Fut, 19 | { 20 | doit: F, 21 | } 22 | 23 | impl Foo 24 | where 25 | Fut: Future, 26 | F: for<'a> Fn(&'a u64) -> Fut, 27 | { 28 | async fn rock(&self) { 29 | let x = 3u64; 30 | (self.doit)(&x).await; 31 | } 32 | } 33 | 34 | fn sing<'a>(_x: &'a u64) -> impl Future + 'a { 35 | async move { 36 | println!("{}", _x); 37 | } 38 | } 39 | 40 | #[tokio::main] 41 | async fn main() { 42 | let _f = Foo { 43 | doit: sing, // Fail to compile 44 | }; 45 | 46 | // _f.rock().await; 47 | } 48 | 49 | // error[E0308]: mismatched types 50 | // --> src/bin/try-it.rs:30:14 51 | // | 52 | // 30 | let _f = Foo { 53 | // | ______________^ 54 | // 31 | | doit: sing, // Fail to compile 55 | // 32 | | }; 56 | // | |_____^ one type is more general than the other 57 | // | 58 | // = note: expected trait `for<'a> fn(&'a u64) -> impl Future + 'a {sing} as FnOnce<(&'a u64,)>>` 59 | // found trait `for<'a> fn(&'a u64) -> impl Future + 'a {sing} as FnOnce<(&'a u64,)>>` 60 | // note: the lifetime requirement is introduced here 61 | // --> src/bin/try-it.rs:6:31 62 | // | 63 | // 6 | F: for<'a> Fn(&'a u64) -> Fut, 64 | // | ^^^ 65 | ``` 66 | 67 | 目前找到的一个解决方法依旧是pin-box一把梭: 68 | 69 | [ok](../rust-playground/src/bin/async-fn-as-generic-pin-box.rs) 70 | 71 | ```rust 72 | use std::future::Future; 73 | use std::pin::Pin; 74 | 75 | struct Foo 76 | where F: for<'a> Fn(&'a u64) -> Pin + 'a>> 77 | { 78 | doit: F, 79 | } 80 | 81 | impl Foo 82 | where F: for<'a> Fn(&'a u64) -> Pin + 'a>> 83 | { 84 | async fn rock(&self) { 85 | let x = 3u64; 86 | (self.doit)(&x).await; 87 | } 88 | } 89 | 90 | fn sing<'a>(_x: &'a u64) -> Pin + 'a>> { 91 | let f = async move { 92 | println!("{}", _x); 93 | }; 94 | Box::pin(f) 95 | } 96 | 97 | #[tokio::main] 98 | async fn main() { 99 | let f = Foo { doit: sing }; 100 | f.rock().await; 101 | } 102 | ``` 103 | -------------------------------------------------------------------------------- /tips/Rust 函数参数 pattern.md: -------------------------------------------------------------------------------- 1 | tags:: tips, rust-programming, pattern 2 | 3 | Rust 中的 pattern match 可以用在 `match` 中, `let`, `if-let`中, 以及函数参数中. 4 | 5 | Rust 函数签名中可以直接 destructure 一个 struct(或其他): 6 | 7 | ```rust 8 | struct Foo { 9 | a: u64, 10 | b: u64, 11 | } 12 | 13 | fn doit(Foo { a, .. }: Foo) { 14 | println!("{a}"); 15 | } 16 | 17 | fn main() { 18 | doit(Foo { a: 3, b: 4 }); 19 | } 20 | ``` 21 | 22 | 23 | [pattern-in-arg](../rust-playground/src/bin/pattern-in-arg.rs) 24 | -------------------------------------------------------------------------------- /tips/Rust 实用文件log创建.md: -------------------------------------------------------------------------------- 1 | tags:: tips, rust-programming, log 2 | 3 | - 首先创建一个滚动切换的文件 `RollingFileAppender`, 可以实现最基本的 Write trait; 4 | 5 | - 但是文件写会阻塞, 影响日志写入性能, 6 | 于是第二步是把它封装到一个 `NonBlocking` 中, NonBlocking 通过一个 channel 连接写入端 7 | 和接受端, 如果接受端满了就丢弃消息. 所以 NonBlocking 虽然很快, 但负载过高会丢消息. 8 | 9 | - 现在这个log写入接口对单笔写入比较高效, 10 | 但整体还是低效, 因为日志写入端会对一行日志的每个小片段都调用一次 `Write::write` 接口. 11 | 例如一段json `{"a":1}` 可能会分成 `{`, `"a"`, `:`, `1`, `}`, 调用5次 12 | `write()`. 13 | 所以最后前端要加个 `BufWriter`, 成批写入, 提升效率. 14 | 15 | [Databend log writer](https://github.com/datafuselabs/fuse-query/blob/11d0057da12f2a1273431723767afbc0ff819f32/src/common/tracing/src/minitrace.rs#L321-L320) 16 | 17 | ```rust 18 | /// Create a `BufWriter` for a rolling file logger. 19 | /// 20 | /// `BufWriter` collects log segments into a whole before sending to underlying writer. 21 | /// `NonBlocking` sends log to another thread to execute the write IO to avoid blocking the thread 22 | /// that calls `log`. 23 | /// 24 | /// Note that `NonBlocking` will discard logs if there are too many `io::Write::write(NonBlocking)`, 25 | /// especially when `fern` sends log segments one by one to the `Writer`. 26 | /// Therefore a `BufWriter` is used to reduce the number of `io::Write::write(NonBlocking)`. 27 | fn new_file_log_writer(dir: &str, name: impl ToString) -> (BufWriter, WorkerGuard) { 28 | let rolling = RollingFileAppender::new(Rotation::HOURLY, dir, name.to_string()); 29 | let (non_blocking, flush_guard) = tracing_appender::non_blocking(rolling); 30 | let buffered_non_blocking = io::BufWriter::with_capacity(64 * 1024 * 1024, non_blocking); 31 | 32 | (buffered_non_blocking, flush_guard) 33 | } 34 | ``` 35 | -------------------------------------------------------------------------------- /tips/Rust 遇到泛型参数手动 reborrow mut ref.md: -------------------------------------------------------------------------------- 1 | tags:: tips, rust-programming, generic, rust-borrow, reborrow, borrow-of-moved 2 | 3 | Rust 编译器会尽量自动对形如 `write(v: &mut Foo)` 的调用进行参数的 **reborrow**: `&mut *v`, 来创建一个临时的 `&mut Foo`,以允许多次调用。但当遇到泛型时,Rust 默认将 `&mut Foo` 直接 move 给目标函数,因此可能导致 `borrow of moved value` 的错误。 4 | 5 | #### 默认对 `&mut V` 的使用自动进行 **reborrow**: 6 | 7 | 下面的代码中 `write(v)` reborrow 后被翻译成 `write(&mut *v)`; reborrow 产生一个临时的 `&mut Foo` move 给目标函数, 所以多次调用 `write(v)` 没有问题的: 8 | 9 | ```rust 10 | fn good(v: &mut Foo) { 11 | write(v); // ---> write(&mut *v) 12 | write(v); // ---> write(&mut *v) 13 | } 14 | 15 | fn write(_v: &mut Foo) {} 16 | ```` 17 | 18 | #### 泛型默认使用 move 19 | 20 | 而遇到 **泛型** 的时候, 泛型可能需要比被调用函数更长的 lifetime, 所以 Rust 这时默认不进行 reborrow, 例如下面 `generic_write(v)` 调用时直接将 `&mut Foo` move 给目标函数, 所以后续代码会产生 **`borrow of moved value`** 的错误. (可变引用 `&mut Foo` 显然不能允许 Copy, 如果也不能 reborrow, 最后只能 move 了): 21 | 22 | ```rust 23 | // error[E0382]: borrow of moved value: `v` 24 | // | 25 | // | fn borrow_of_moved_error(v: &mut Foo) { 26 | // | - move occurs because `v` has type `&mut Foo`, 27 | // | which does not implement the `Copy` trait 28 | // | generic_write(v); 29 | // | - value moved here 30 | // | write(v); 31 | // | ^ value borrowed here after move 32 | fn borrow_of_moved_error(v: &mut Foo) { 33 | generic_write(v); // ---> generic_write(v); 34 | write(v); // ---> write(&mut *v); 35 | } 36 | 37 | fn generic_write(_v: V) {} 38 | fn write(_v: &mut Foo) {} 39 | ```` 40 | 41 | #### 带泛型时需要手动 reborrow 42 | 43 | 解决这个问题的方法是使用 `&mut *v` 手动进行 reborrow, 或强制指定泛型类型: 44 | 45 | ```rust 46 | fn solution(v: &mut Foo) { 47 | generic_write(&mut *v); // Manually reborrow 48 | write(v); 49 | } 50 | 51 | fn solution_2(v: &mut Foo) { 52 | generic_write::<&mut Foo>(v); // Specify the type for generic type 53 | write(v); 54 | } 55 | 56 | fn generic_write(_v: V) {} 57 | fn write(_v: &mut Foo) {} 58 | ``` 59 | 60 | --- 61 | 62 | - 代码例子: [manually-reborrow.rs](../rust-playground/src/bin/borrow-of-moved-reborrow.rs) 63 | - Issue: https://github.com/rust-lang/rust/issues/62112 64 | - 感谢帮忙解决问题的懂哥们: 65 | [walter](https://github.com/w41ter) @github 66 | [Winter Zhang](https://github.com/zhang2014) @github 67 | [Xuanwo](https://github.com/Xuanwo) @github 68 | 69 | 70 | -------------------------------------------------------------------------------- /tips/Tokio 中 hang 死所有 worker 的方法.md: -------------------------------------------------------------------------------- 1 | tags:: tips, rust-programming, tokio, blocking, schedule 2 | 3 | 4 | [Tokio](https://github.com/tokio-rs/tokio) 的 task(一个Future) 里如果使用了阻塞调用, 例如 `std::sync::Mutex`, 5 | 会阻塞当前的 tokio-worker 线程, 这个 worker 无法再执行其他 task. 6 | 所以代码里如果不可避免的有(少量的)阻塞调用, 就要为 runtime 启动更多的 worker 线程, 7 | 保证存在没被阻塞的 worker 来执行待调度的 task, 以避免整个tokio runtime 完全 hang 住(有 task 但没 worker 运行它). 8 | 9 | 但现实是, 就算 worker 再多, tokio 也可能造成永久性的阻塞. 10 | 11 | 原因是 tokio 里的待执行 task 不是简单的放到一个queue里, 12 | 除了 runtime 内共享的, 可被每个 worker 消费的 [`run_queue`](https://github.com/tokio-rs/tokio/blob/5b947ca2c78ac96f61ef4d4d17d9a1fc16e446c6/tokio/src/runtime/thread_pool/worker.rs#L101), 每个 worker 还有一个自己的 [`lifo_slot`](https://github.com/tokio-rs/tokio/blob/5b947ca2c78ac96f61ef4d4d17d9a1fc16e446c6/tokio/src/runtime/thread_pool/worker.rs#L98), 13 | 只存储一个最后被放入的 task (目的是减小调度延迟). `lifo_slot` 只由它所属的 worker 使用, 里面存储的 task 不能被其他 worker 执行. 14 | 由于这个结构, 构造 hang 住的方法是如图所示: 15 | 16 | - Future f1 被 runtime-1 执行, 持有一个 async 的锁 `m` 后, 返回了 `Pending`, 17 | 这时它被调度到 worker-1 本地的 `lifo_slot`. 18 | 19 | - Future f2 在 runtime-1 执行后返回 `Pending`, 被放入共享队列 `run_queue`. 20 | 21 | - Future f3 在 runtime-1 中执行, 它将一个任务 `f4` 交给其他的 runtime 去完成(例如为了隔离网络IO和本地磁盘IO), 22 | 使用 [`block_on(f4)`](https://docs.rs/tokio/latest/tokio/runtime/struct.Runtime.html#method.block_on) 23 | 的方式, 等待执行结果返回. 24 | 25 | - f4 中也需要锁 `m`, 等待. 26 | 27 | 28 | 这时, f2 在共享队列 `run_queue` 中, 可以被执行, 但是 f1 在 worker-1 本地的 `lifo_slot` 里, 29 | 只能由 worker-1 调度, 但 worker-1 当前阻塞在 f3. 30 | 于是等待关系形成了一个环: `f4 → m(f1) → f3 → f4`, hang死任务达成. 31 | 32 | ![](../assets/tokio-blocking-hangs/hang.excalidraw.png) 33 | -------------------------------------------------------------------------------- /tips/databend/profiling/174307263-a2c9bbe6-e417-48b7-bf4d-cbbbaad03a6e.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/drmingdrmer/tips/047f274864fb33ac7f6da89eba8e806ac6edb49c/tips/databend/profiling/174307263-a2c9bbe6-e417-48b7-bf4d-cbbbaad03a6e.png -------------------------------------------------------------------------------- /tips/databend/profiling/204963954-f6eacf10-d8bd-4469-9c8d-7d30955f1a78.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/drmingdrmer/tips/047f274864fb33ac7f6da89eba8e806ac6edb49c/tips/databend/profiling/204963954-f6eacf10-d8bd-4469-9c8d-7d30955f1a78.png -------------------------------------------------------------------------------- /tips/jemalloc/jemalloc-tips.md: -------------------------------------------------------------------------------- 1 | - Use "prof:true,prof_active:false" to make it possible to profile memory without restarting. 2 | - https://jemalloc.net/jemalloc.3.html 3 | - pytorch tuning: jemalloc 4 | https://intel.github.io/intel-extension-for-pytorch/latest/tutorials/performance_tuning/tuning_guide.html 5 | - 6 | - [[profiling-databend]] -------------------------------------------------------------------------------- /tips/latex-util.md: -------------------------------------------------------------------------------- 1 | tags:: latex 2 | 3 | - Online math editor, image ORC, export etc. 4 | https://www.latexlive.com/home 5 | - tex live 6 | - mik tex 7 | - https://www.overleaf.com 8 | - **XeTeX** tex engine 9 | https://en.wikipedia.org/wiki/XeTeX 10 | is bundled with [TeX Live](https://en.wikipedia.org/wiki/TeX_Live), [MacTeX](https://en.wikipedia.org/wiki/MacTeX), [MiKTeX](https://en.wikipedia.org/wiki/MiKTeX) and [Lyx](https://en.wikipedia.org/wiki/Lyx) (see the [History](https://en.wikipedia.org/wiki/XeTeX#History) below for dates and versions). 11 | - 12 | - **TeXmacs** by GNU is a free scientific editing platform designed to create beautiful technical documents using a wysiwyg interface 13 | https://www.texmacs.org/tmweb/home/welcome.en.html 14 | - 15 | - **MacTex**: all-in-one tex suite: include: LaTeX, XeLaTeX, LuaLaTeX.. and editer TeXShop 16 | https://www.tug.org/mactex/ 17 | #install `brew install mactex` 18 | - **What Is Installed** 19 | - TeX Live, which contains TeX, LaTeX, AMS-TeX, and virtually every TeX-related style file and font. TeX Live is maintained by TeX User Groups across the world. TeX Live is compiled from the same sources for all platforms: Macintosh, Windows, Linux, Unix. 20 | - MacTeX also installs the GUI programs TeXShop, LaTeXiT, TeX Live Utility, and BibDesk. 21 | - MacTeX installs Ghostscript, an open source version of Postscript. Two optional packages install libgs, the dynamical library for Ghostscript, and mutool, an extra tool. These tools are used by only one program in TeX Live, dvisvgm. So they are not installed by default, but can be obtained using the "custom install" option in MacTeX. 22 | - 23 | - **Texifier** 24 | ✅ Just download and use. 25 | Not free 26 | https://www.texifier.com/ 27 | - 28 | - [[test-image]] 29 | - 30 | - ### Latex example/template 31 | - 老c的: https://github.com/lichuang/my-latex-template 32 | - 老c推荐的: https://github.com/ElegantLaTeX/ElegantBook 33 | - 34 | - Add katex math to docs.rs 35 | https://stackoverflow.com/questions/46495063/how-to-write-math-formulas-for-rust-documentation 36 | - 37 | - -------------------------------------------------------------------------------- /tips/life/急性肠胃炎.md: -------------------------------------------------------------------------------- 1 | - 口服补液盐(Oral Rehydration Salt)(ORS)是世界卫生组织推荐的治疗急性腹泻脱水有优异疗效的药物,处方组成合理,方便高效,其纠正脱水的速度优于静脉滴注。 该药虽为口服制剂,但要强调规范的配制方法,使含量准确以确保疗效。 口服补液盐含有氯化钠、氯化钾、碳酸氢钠(或枸橼酸钠)和葡萄糖。 2 | - 蒙脱石散(英语:Diosmectite),商品名为思密达(Smecta),是一种用于急性和慢性腹泻的治疗的药物,含双八面体蒙脱石微粉。 3 | https://zh.wikipedia.org/wiki/蒙脱石散 4 | -------------------------------------------------------------------------------- /tips/life/隔音-2024-08/imgs/20cm实物图.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/drmingdrmer/tips/047f274864fb33ac7f6da89eba8e806ac6edb49c/tips/life/隔音-2024-08/imgs/20cm实物图.jpg -------------------------------------------------------------------------------- /tips/life/隔音-2024-08/imgs/价格表.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/drmingdrmer/tips/047f274864fb33ac7f6da89eba8e806ac6edb49c/tips/life/隔音-2024-08/imgs/价格表.jpg -------------------------------------------------------------------------------- /tips/life/隔音-2024-08/imgs/安装步骤.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/drmingdrmer/tips/047f274864fb33ac7f6da89eba8e806ac6edb49c/tips/life/隔音-2024-08/imgs/安装步骤.png -------------------------------------------------------------------------------- /tips/life/隔音-2024-08/imgs/超薄减震器.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/drmingdrmer/tips/047f274864fb33ac7f6da89eba8e806ac6edb49c/tips/life/隔音-2024-08/imgs/超薄减震器.jpg -------------------------------------------------------------------------------- /tips/life/隔音-2024-08/imgs/超薄实物图.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/drmingdrmer/tips/047f274864fb33ac7f6da89eba8e806ac6edb49c/tips/life/隔音-2024-08/imgs/超薄实物图.jpg -------------------------------------------------------------------------------- /tips/life/隔音-2024-08/imgs/超薄食物细节.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/drmingdrmer/tips/047f274864fb33ac7f6da89eba8e806ac6edb49c/tips/life/隔音-2024-08/imgs/超薄食物细节.jpg -------------------------------------------------------------------------------- /tips/life/隔音-2024-08/安装步骤.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/drmingdrmer/tips/047f274864fb33ac7f6da89eba8e806ac6edb49c/tips/life/隔音-2024-08/安装步骤.png -------------------------------------------------------------------------------- /tips/life/隔音-2024-08/隔音-2024-08.md: -------------------------------------------------------------------------------- 1 | - 品牌: soundbox声博士 2 | - 套餐商品链接: 3 | https://detail.tmall.com/item.htm?id=657177228009&spm=2015.23436601.0.0 4 | - 套餐: 声博士超博减震, 其中部分材料自选. 5 | - 整体: 减震器 接 龙骨 接 隔音板, 内填装隔音棉. 其他材料包括螺丝, 密封胶 等. 6 | - ![安装步骤](imgs/安装步骤.png) 7 | - ![超薄减震器.jpg](imgs/超薄减震器.jpg) 8 | 9 | ![超薄实物图.jpg](imgs/超薄实物图.jpg) 10 | 11 | ![超薄食物细节.jpg](imgs/超薄食物细节.jpg) 12 | - 隔音棉: 13 | - 选择: 拜耳声学棉: 14 | https://detail.tmall.com/item.htm?spm=a1z10.3-b-s.w4011-15725740278.47.31091560HIMc7e&id=581854963623&rn=f7fb13cd99e7fd6dbe4410bb3b65bcf3&abbucket=9 15 | - 隔音板: 16 | - 选择: 石膏板+高分子阻尼隔音毡(3mm)+石膏板: 17 | - 本地买石膏板, 淘宝卖隔音毡: 18 | - 石膏板12mm: 7kg/m^2 ~ 10kg/m^2 19 | - 未选(因为运输太重了...): G15E 1220*1220*12mm 一张1.48平方米,重量是27.5kg 18kg/m^2 仅有淘宝有 https://detail.tmall.com/item.htm?id=541388282947&spm=2015.23436601.0.0 20 | - > 我们的图片是隔音毡的结构,这个比较轻一些,一般家庭容易接受一些; 石膏板+隔音毡+石膏板夹层结构是隔音板的替代结构 21 | - 隔音毡: 22 | - 选择: 高分子阻尼隔音毡 3MM 23 | https://detail.tmall.com/item.htm?id=534664384678&spm=2015.23436601.0.0 24 | - 未选: G10: 25 | https://detail.tmall.com/item.htm?id=540407471911&spm=2015.23436601.0.0 26 | - 运输: 27 | 周一到周五,16点前付款当天发的 28 | 北京大概3-5天的了 29 | - 安装: 30 | 下安装单并且到货通知后的3至5天,最晚不会超过7个工作日能上门安装,师傅会提前一两天联系预约时间的。咱们隔音只做到石膏板这一层,不含刮腻子和刷油漆的哈,并且完后的垃圾需要您自行处理的,如需清运垃圾请提前沟通协商费用。如果天花或墙体是空心的(预制板或夹板)请一定要提前告知我们。 31 | - 可以介绍安装师傅,安装费用大概是260元左右一平方(以跟安装师傅协商的费用为准)一般镇以上的都可以安排。 32 | 安装费用含辅材:轻钢龙骨、膨胀螺丝和石膏板。 33 | 10平方起做,不足10平方按10平方收费哦。 34 | 安装不是捆绑的哈,也可以当地找师傅,我们提供指导呢 35 | - --- 36 | - 房间大小: 37 | 363cm*263cm 38 | - 施工时间: 2-3天 39 | - 产品费+运费+上楼+安装方收的费用 40 | - 41 | - 42 | - 价格: 43 | 隔音毡: 253/m^2 44 | 声学棉: 184/m^2 45 | - 当前费用: 46 | 5225 淘宝买材料 47 | 50 搬上楼费用 48 | 1200 微信转 安装费1 49 | 1400 淘宝拍 安装费2 50 | ![价格表.jpg](imgs/价格表.jpg) 51 | - 52 | - 其他资源: 53 | - 声博士官网: 54 | - 碳塑隔声板 55 | https://www.soundbox.hk/sound-insulation-damping-system/sound-insulation-board/ 56 | - 高分子隔声毡 57 | https://www.soundbox.hk/sound-insulation-damping-system/high-polymer-sound-insulation-felt/ 58 | - 超薄减振器 59 | https://www.soundbox.hk/sound-insulation-damping-system/vibration-absorber/ 60 | - -------------------------------------------------------------------------------- /tips/lldb/lldb默认拦截signal, 需要设置pass.md: -------------------------------------------------------------------------------- 1 | lldb attach 进程后默认会拦截各种 signal,如果要调试 signal handle 的逻辑,需要设置 pass 放行。(gdb 同理,不过命令有些许不同 2 | 3 | ``` 4 | pro handle -p true -s false SIGINT 5 | ``` 6 | -------------------------------------------------------------------------------- /tips/math/complex-analysis/Complex conjugate root theorem 共轭复根定理.md: -------------------------------------------------------------------------------- 1 | tags:: tips, math, math-complex-analysis 2 | 3 | https://en.wikipedia.org/wiki/Complex_conjugate_root_theorem 4 | 5 | In mathematics, the complex conjugate root theorem states that if P is a polynomial in one variable with real coefficients, and a + bi is a root of P with a and b real numbers, then its complex conjugate a − bi is also a root of P. 6 | -------------------------------------------------------------------------------- /tips/math/math-combinatorics.md: -------------------------------------------------------------------------------- 1 | tags:: tips, math, math-combinatorics 2 | 3 | 4 | - https://en.wikipedia.org/wiki/Stirling_numbers_of_the_second_kind #read 5 | - 错排问题: 6 | https://zh.wikipedia.org/wiki/%E9%94%99%E6%8E%92%E9%97%AE%E9%A2%98 #read 其他解法? 7 | - 8 | -------------------------------------------------------------------------------- /tips/math/math-complex-analysis.md: -------------------------------------------------------------------------------- 1 | tags:: tips, math, math-complex-analysis 2 | 3 | - Tips 4 | -------------------------------------------------------------------------------- /tips/math/math-field.md: -------------------------------------------------------------------------------- 1 | - 2 | - 3 | - -------------------------------------------------------------------------------- /tips/math/math-group.md: -------------------------------------------------------------------------------- 1 | ### 半群 2 | S×S→S。若·满足结合律,即: 3 | ∀x,y,z∈S,有(x·y)·z=x·(y·z) 4 | - ### 幺半群 5 | 是一个带有二元运算 `*`: M × M → M 的集合 M ,其符合下列公理: 6 | 结合律:对任何在 M 内的a、b、c , `(a·b)·c = a·(b·c)` 。 7 | 单位元:存在一在 M 内的元素e,使得任一于 M 内的 a 都会符合 a*e = e*a = a 。 8 | 9 | **幺半群** 也可以说是带有单位元的**半群** 10 | - ### order 阶数 (群) 11 | - 一个群的阶是指其势,即其元素的个数; 12 | - 一个群内的一个元素a之阶(有时称为周期)是指会使得am = e的最小正整数m(其中的e为这个群的单位元素,且am为a的m次幂)。若没有此数存在,则称a有无限阶。有限群的所有元素有有限阶。 13 | 14 | 一个群G的阶被标记为ord(G)或|G|,而一个元素的阶则标记为ord(a)或|a|。 15 | [Order](https://en.wikipedia.org/wiki/Order_(group_theory)) 16 | - ### normal subgroup 正规子群 17 | https://en.wikipedia.org/wiki/Normal_subgroup 18 | 19 | 群G的子群N是正规子群,如果它在共轭变换下不变;就是说对于每个N中元素n和每个G中的元素g,元素gng−1仍在N中。我们写为 20 | 21 | $$ 22 | N \triangleleft G, \Leftrightarrow \forall n \in {N}, \forall g \in G, gng^{-1} \in N 23 | $$ 24 | 25 | 下列条件等价于子群 N 在 G 中是正规子群。其中任何一个都可以用作定义: 26 | 27 | 对于 G 中的所有g,$gNg^{-1} ⊆ N$。 28 | 对于 G 中的所有g,$gNg^[−1] = N$。 29 | N 在 G 中的左陪集的集合和右陪集的集合是一致的。 30 | 对于 G 中的所有g,gN = Ng。 31 | N 是 G 的若干共轭类的并集。 32 | 存在以 N 为核的 G 的群同态。 33 | - ### Index of a subgroup 34 | Formally, the index of H in G is defined as the number of cosets of H in G. 35 | 36 | The index of H in G is usually denoted |G : H| or [G : H] or (G:H) 37 | 38 | If G and H are finite groups, then the index of H in G is equal to the quotient of the orders of the two groups: 39 | $$ 40 | |G:H| = \frac{|G|}{|H|}. 41 | $$ 42 | - ### quotient group 43 | Let N be a normal subgroup of a group G. 44 | We define the set G/N to be the set of all left cosets of N in G, i.e., G/N = { aN : a ∈ G }. 45 | Define an operation on G/N as follows. 46 | For each aN and bN in G/N, the product of aN and bN is (aN)(bN). 47 | This defines an operation on G/N, because we have the following equalities of subsets of G: 48 | 49 | (aN)(bN) = a(Nb)N = a(bN)N = (ab)NN = (ab)N -------------------------------------------------------------------------------- /tips/math/math-probability.md: -------------------------------------------------------------------------------- 1 | tags:: tips, math, math-probability 2 | -------------------------------------------------------------------------------- /tips/math/math.md: -------------------------------------------------------------------------------- 1 | tags:: tips, math 2 | 3 | - TODO: 4 | - hyperloglog 5 | - catalan number: https://en.wikipedia.org/wiki/Catalan_number 6 | - hamilton's quaternions 7 | Hamilton defined a quaternion as **the quotient of two directed lines in tridimensional space; or, more generally, as the quotient of two vectors**. A quaternion can be represented as the sum of a scalar and a vector. It can also be represented as the product of its tensor and its versor. 8 | https://en.wikipedia.org/wiki/Classical_Hamiltonian_quaternions 9 | - homomorphism from A to A 10 | https://en.wikipedia.org/wiki/Algebra_homomorphism 11 | [[homomorphism]] 12 | - https://en.wikipedia.org/wiki/Directed_acyclic_graph 13 | - https://en.m.wikipedia.org/wiki/Weak_ordering 14 | - https://en.wikipedia.org/wiki/Space-filling_curve 15 | - https://en.wikipedia.org/wiki/Z-order_curve 16 | - 对称多项式 https://zh.wikipedia.org/wiki/%E5%B0%8D%E7%A8%B1%E5%A4%9A%E9%A0%85%E5%BC%8F 17 | - LP范数: https://zh.wikipedia.org/zh-cn/Lp%E8%8C%83%E6%95%B0 18 | $L_{p}({\vec {x}})=\lVert {\vec {x}}\rVert _{p}={\Bigl (}\sum _{i=1}^{n}|x_{i}|^{p}{\Bigr )}^{1/p},\qquad {\vec {x}}=\{x_{1},x_{2},\ldots ,x_{n}\},\,p\geqslant 1.$ 19 | - 范数 20 | https://zh.wikipedia.org/wiki/%E8%8C%83%E6%95%B0 21 | - 22 | - #### How do you show that the degree of an irreducible polynomial over the reals is either one or two? 23 | https://math.stackexchange.com/questions/1116965/how-do-you-show-that-the-degree-of-an-irreducible-polynomial-over-the-reals-is-e 24 | - 25 | - 26 | - [[lie group]] 27 | - 28 | - [[order-dimension@math]] 29 | - 30 | - [[math-combinatorics]] 31 | - [[math-complex-analysis]] 32 | - [[math-field]] 33 | - [[math-group]] 34 | - 35 | - [[fractal]] 36 | - --- 37 | - [[math-mid-school-geometry]] 38 | - 39 | - --- 40 | - [[Algebraic extension 代数扩张]] 41 | - [[Characteristic 特征(algebra)]] 42 | - [[Formal derivative 形式导数]] 43 | - [[Partially Ordered Set 偏序关系]] 44 | - [[Repeated root 重根]] 45 | - [[Separable extension 可分扩张(field)]] -------------------------------------------------------------------------------- /tips/math/mid-school-geometry/DEF 为正三角形 AD=BF=CE 求证 ABC为正三角形.md: -------------------------------------------------------------------------------- 1 | 2 | 3 | this is a triagle $$x= 3$$ -------------------------------------------------------------------------------- /tips/math/mid-school-geometry/Makefile: -------------------------------------------------------------------------------- 1 | all: 2 | find . -name "*.tex" -print0 | xargs -0 basename -s .tex -a | xargs -I '{}' pdfcrop '{}.pdf' '{}-cropped.pdf' 3 | find . -name "*-cropped.pdf" -print0 | xargs -0 basename -s .pdf -a | xargs -I '{}' convert -density 150 '{}.pdf' -quality 90 '{}.jpg' 4 | -------------------------------------------------------------------------------- /tips/math/mid-school-geometry/question-and-answer-cropped.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/drmingdrmer/tips/047f274864fb33ac7f6da89eba8e806ac6edb49c/tips/math/mid-school-geometry/question-and-answer-cropped.jpg -------------------------------------------------------------------------------- /tips/math/mid-school-geometry/question-and-answer-cropped.pdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/drmingdrmer/tips/047f274864fb33ac7f6da89eba8e806ac6edb49c/tips/math/mid-school-geometry/question-and-answer-cropped.pdf -------------------------------------------------------------------------------- /tips/math/mid-school-geometry/question-and-answer.pdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/drmingdrmer/tips/047f274864fb33ac7f6da89eba8e806ac6edb49c/tips/math/mid-school-geometry/question-and-answer.pdf -------------------------------------------------------------------------------- /tips/math/mid-school-geometry/question-and-answer.tex: -------------------------------------------------------------------------------- 1 | %!TEX encoding = UTF-8 2 | 3 | 4 | \documentclass[UTF8]{ctexart} 5 | 6 | \usepackage{tikz} 7 | \usepackage{amssymb} 8 | \usepackage{amsmath} 9 | 10 | \usetikzlibrary{calc} 11 | \usepackage{fontspec} 12 | 13 | % Set up a font that supports Chinese characters 14 | % \setmainfont{SimSun}[Path=./] % Specify the path if the font is not in the system fonts 15 | % Alternatively, you can use other fonts like: 16 | % \setmainfont{Microsoft YaHei} 17 | % \setmainfont{NotoSansCJKsc-Regular.otf} 18 | 19 | 20 | \setmainfont{Noto Sans CJK SC} 21 | 22 | 23 | \begin{document} 24 | 25 | △DEF 为正三角形 AD=BE=CF 26 | 27 | 求证 △ABC为正三角形 28 | 29 | 30 | \begin{tikzpicture}[scale=6] 31 | % Define coordinates for the outer equilateral triangle 32 | \coordinate (A) at (0, {sqrt(3)/2}); 33 | \coordinate (B) at (-0.5, 0); 34 | \coordinate (C) at (0.5, 0); 35 | 36 | % Define D relative to A (1/3 of the way down from A) 37 | \coordinate (D) at ($(A)!1/3!(B)$); 38 | \coordinate (E) at ($(B)!1/3!(C)$); 39 | \coordinate (F) at ($(C)!1/3!(A)$); 40 | 41 | % Draw the main triangle 42 | \draw (A) -- (B) -- (C) -- cycle; 43 | 44 | % Draw internal lines 45 | \draw (D) -- (E) -- (F) -- cycle; 46 | 47 | % Label points 48 | \node[above] at (A) {A}; 49 | \node[below left] at (B) {B}; 50 | \node[below right] at (C) {C}; 51 | \node[left] at (D) {D}; 52 | \node[below] at (E) {E}; 53 | \node[right] at (F) {F}; 54 | 55 | \node at ($(A) + (0, -0.1)$) {$\alpha$}; 56 | \node at ($(B) + (0.1, 0.07)$) {$\beta$}; 57 | \node at ($(C) + (-0.1, 0.07)$) {$\theta$}; 58 | 59 | 60 | % length `u` 61 | \node at ($(A)!0.5!(D)$) [left] {u}; 62 | \node at ($(B)!0.5!(E)$) [below] {u}; 63 | \node at ($(C)!0.5!(F)$) [right] {u}; 64 | 65 | % length `l` 66 | \node at ($(D)!0.5!(E)$) [left] {l}; 67 | \node at ($(E)!0.5!(F)$) [below] {l}; 68 | \node at ($(F)!0.5!(D)$) [above] {l}; 69 | 70 | \end{tikzpicture} 71 | 72 | 73 | 74 | 75 | 76 | 假设 77 | $\angle \alpha < \angle \theta$ 78 | 79 | 80 | \begin{align} 81 | 82 | \angle \alpha > \angle \theta 83 | 84 | \because \cos \alpha = \frac{u^2 + |AF|^2 - l^2}{2 u |AF|} = \frac{u^2 + x^2 - l^2}{2 u x} 85 | 86 | \therefore (\cos \alpha)' &= (\frac{(u^2 - l^2)}{2u} \frac{1}{x} + \frac{x}{2u})' 87 | &= \frac{(l^2 - u^2)}{2u} \frac{1}{x^2} + \frac{1}{2u} 88 | 89 | 90 | 91 | \end{align} 92 | 93 | 如果 $l > u$, 随着 $\alpha$ 增大 $|AF|$ 减小 94 | 95 | \begin{align} 96 | 97 | \angle \alpha < \angle \theta 98 | 99 | => |AF| < |CE| 100 | 101 | => |AC| < |BC| 102 | 103 | => \angle \beta < \angle \alpha 104 | 105 | => |BD| > |AF| 106 | 107 | => |AB| > |AC| 108 | 109 | => \angle \theta > \angle \beta 110 | 111 | => |CE| < |BD| 112 | 113 | => |BC| < |AB| 114 | 115 | => \angle \alpha > \angle \theta 116 | 117 | \end{align} 118 | 119 | \end{document} 120 | -------------------------------------------------------------------------------- /tips/math/mid-school-geometry/question-cropped.pdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/drmingdrmer/tips/047f274864fb33ac7f6da89eba8e806ac6edb49c/tips/math/mid-school-geometry/question-cropped.pdf -------------------------------------------------------------------------------- /tips/math/mid-school-geometry/question.pdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/drmingdrmer/tips/047f274864fb33ac7f6da89eba8e806ac6edb49c/tips/math/mid-school-geometry/question.pdf -------------------------------------------------------------------------------- /tips/math/mid-school-geometry/question.tex: -------------------------------------------------------------------------------- 1 | %!TEX encoding = UTF-8 2 | 3 | 4 | \documentclass[UTF8]{ctexart} 5 | 6 | \usepackage{tikz} 7 | \usepackage{amssymb} 8 | \usepackage{amsmath} 9 | 10 | \usetikzlibrary{calc} 11 | \usepackage{fontspec} 12 | 13 | % Set up a font that supports Chinese characters 14 | % \setmainfont{SimSun}[Path=./] % Specify the path if the font is not in the system fonts 15 | % Alternatively, you can use other fonts like: 16 | % \setmainfont{Microsoft YaHei} 17 | % \setmainfont{NotoSansCJKsc-Regular.otf} 18 | 19 | 20 | \setmainfont{Noto Sans CJK SC} 21 | 22 | 23 | \begin{document} 24 | 25 | △DEF 为正三角形 AD=BE=CF 26 | 27 | 求证 △ABC为正三角形 28 | 29 | 30 | \begin{tikzpicture}[scale=6] 31 | % Define coordinates for the outer equilateral triangle 32 | \coordinate (A) at (0, {sqrt(3)/2}); 33 | \coordinate (B) at (-0.5, 0); 34 | \coordinate (C) at (0.5, 0); 35 | 36 | % Define D relative to A (1/3 of the way down from A) 37 | \coordinate (D) at ($(A)!1/3!(B)$); 38 | \coordinate (E) at ($(B)!1/3!(C)$); 39 | \coordinate (F) at ($(C)!1/3!(A)$); 40 | 41 | % Draw the main triangle 42 | \draw (A) -- (B) -- (C) -- cycle; 43 | 44 | % Draw internal lines 45 | \draw (D) -- (E) -- (F) -- cycle; 46 | 47 | % Label points 48 | \node[above] at (A) {A}; 49 | \node[below left] at (B) {B}; 50 | \node[below right] at (C) {C}; 51 | \node[left] at (D) {D}; 52 | \node[below] at (E) {E}; 53 | \node[right] at (F) {F}; 54 | 55 | \node at ($(A) + (0, -0.1)$) {$\alpha$}; 56 | \node at ($(B) + (0.1, 0.07)$) {$\beta$}; 57 | \node at ($(C) + (-0.1, 0.07)$) {$\theta$}; 58 | 59 | 60 | % length `u` 61 | \node at ($(A)!0.5!(D)$) [left] {u}; 62 | \node at ($(B)!0.5!(E)$) [below] {u}; 63 | \node at ($(C)!0.5!(F)$) [right] {u}; 64 | 65 | % length `l` 66 | \node at ($(D)!0.5!(E)$) [left] {l}; 67 | \node at ($(E)!0.5!(F)$) [below] {l}; 68 | \node at ($(F)!0.5!(D)$) [above] {l}; 69 | 70 | \end{tikzpicture} 71 | 72 | \end{document} 73 | -------------------------------------------------------------------------------- /tips/math/order-dimension/infinite-poset-2d@math@order-dimension.md: -------------------------------------------------------------------------------- 1 | by AI o1-preview 2 | 3 | **是的,存在无限元素的偏序集合,其序维度为2。以下我将提供一个具体的例子,并详细解释为什么其序维度是2。** 4 | 5 | --- 6 | 7 | ### **例子:二维平面上的特定点集** 8 | 9 | #### **定义偏序集合 $P$** 10 | 11 | 考虑以下偏序集合 $P$,其元素是所有有序对 $(n, 0)$ 和 $(n, 1)$,其中 $n$ 是自然数,即: 12 | 13 | $$ 14 | P = \{ (n, 0),\ (n, 1) \mid n \in \mathbb{N} \} 15 | $$ 16 | 17 | **偏序关系定义如下:** 18 | 19 | 1. **在每个固定的 $n$ 下:** 20 | 21 | $$ 22 | (n, 0) \leq (n, 1) 23 | $$ 24 | 25 | 2. **按照自然数 $n$ 的大小:** 26 | 27 | - 对于所有 $n < m$,有: 28 | 29 | $$ 30 | (n, 0) \leq (m, 0) 31 | $$ 32 | 33 | $$ 34 | (n, 1) \leq (m, 1) 35 | $$ 36 | 37 | 3. **跨越不同的 $n$ 和不同的 $(0, 1)$:** 38 | 39 | - 除了上述关系外,其他元素之间没有偏序关系。 40 | 41 | **图示:** 42 | 43 | ``` 44 | (1,0) --(1,1) 45 | | 46 | (2,0) --(2,1) 47 | | 48 | (3,0) --(3,1) 49 | | 50 | ... 51 | ``` 52 | 53 | - 竖直方向上,$(n, 0)$ 构成一条链。 54 | - 在每个 $n$,有 $(n, 0) \leq (n, 1)$。 55 | - $(n, 1)$ 也按 $n$ 的顺序形成一条链。 56 | 57 | --- 58 | 59 | ### **为什么序维度为 2?** 60 | 61 | #### **(1) 构造两个线性扩展** 62 | 63 | **线性扩展 1 ($L_1$):** 64 | 65 | 按照以下顺序排列所有元素: 66 | 67 | $$ 68 | (1, 0) < (1, 1) < (2, 0) < (2, 1) < (3, 0) < (3, 1) < \dots 69 | $$ 70 | 71 | **线性扩展 2 ($L_2$):** 72 | 73 | 按照以下顺序排列所有元素: 74 | 75 | $$ 76 | (1, 0) < (2, 0) < (3, 0) < \dots < (1, 1) < (2, 1) < (3, 1) < \dots 77 | $$ 78 | 79 | #### **(2) 验证两个线性扩展的交集还原原始偏序关系** 80 | 81 | **在 $L_1$ 中:** 82 | 83 | - $(n, 0) < (n, 1)$,满足条件。 84 | - $(n, 1) < (n+1, 0)$,这是线性扩展引入的额外关系,不在原始偏序关系中。 85 | 86 | **在 $L_2$ 中:** 87 | 88 | - $(n, 0) < (n+1, 0)$,满足纵向的偏序关系。 89 | - 所有的 $(n, 0)$ 均小于所有的 $(m, 1)$,其中 $n < m$。 90 | 91 | #### **(3) 两个线性扩展的交集恰好是原始的偏序关系** 92 | 93 | - **共同的序关系:** 94 | 95 | - $(n, 0) \leq (n, 1)$:在两个线性扩展中均满足。 96 | - $(n, 0) \leq (m, 0)$,当 $n \leq m$:在两个线性扩展中均满足。 97 | - $(n, 1) \leq (m, 1)$,当 $n \leq m$:在两个线性扩展中均满足。 98 | 99 | - **不在原始偏序关系中的序关系:** 100 | 101 | - 在 $L_1$ 中,$(n, 1) < (n+1, 0)$,这不是原始偏序关系,需要被排除。 102 | - 由于两个线性扩展的交集只保留在所有线性扩展中一致的序关系,因此这些额外的序关系在交集中被排除。 103 | 104 | #### **(4) 不能用一个线性扩展表示全部偏序关系** 105 | 106 | - **单个线性扩展的问题:** 107 | 108 | - 任意一个单独的线性扩展都会引入额外的序关系,使得一些原本不可比的元素变得可比。 109 | - 例如,在 $L_1$ 中,$(n, 1) < (n+1, 0)$,但在原始偏序关系中,这两个元素是不可比较的。 110 | 111 | - **需要至少两个线性扩展:** 112 | 113 | - 两个线性扩展的交集恰好能够去除这些额外的序关系,精确地表达原始的偏序关系。 114 | 115 | #### **(5) 证明序维度为2** 116 | 117 | - **结论:** 因此,**序维度为2**,因为需要且只需要两个线性扩展,其交集能够完全表示偏序集合 $P$ 的偏序关系。 118 | 119 | --- 120 | 121 | ### **进一步的解释** 122 | 123 | #### **(a) 为什么序维度不是 1** 124 | 125 | - **若只有一个线性扩展:** 126 | 127 | - 无法避免引入额外的序关系,使得原本不可比较的元素变得可比。 128 | - 例如,在任何一个全序中,所有元素都必须按照某种顺序排列,这会破坏原始偏序集合中的不可比较性。 129 | 130 | #### **(b) 为什么序维度不是无限大** 131 | 132 | - **虽然集合是无限的,但偏序关系的复杂度有限。** 133 | - **存在两个线性扩展即可完全刻画所有的偏序关系,因此序维度为2。** 134 | 135 | --- 136 | 137 | ### **关于无限元素偏序集合序维度有限的讨论** 138 | 139 | - **存在许多无限的偏序集合,其序维度是有限的。** 140 | - **序维度反映的是偏序关系的复杂度,而不是元素的数量。** 141 | 142 | **例如:** 143 | 144 | - **自然数的全序集合 $(\mathbb{N}, \leq)$:** 145 | 146 | - 是一个无限的偏序集合,其序维度为1。 147 | 148 | - **上述例子构造的偏序集合 $P$:** 149 | 150 | - 虽然元素无限,但偏序关系的复杂度有限,序维度为2。 151 | 152 | --- 153 | 154 | ### **结论** 155 | 156 | - **是的,存在无限元素的偏序集合,其序维度为2。** 157 | - **通过构造特定的偏序集合,并证明只需两个线性扩展即可完全刻画其偏序关系,证明了序维度为2。** 158 | - **这个例子说明了序维度反映的是偏序关系的复杂性,而不是元素数量的多少。** 159 | 160 | --- 161 | 162 | ### **附加说明** 163 | 164 | - **序维度与元素数量的关系:** 165 | 166 | - 虽然元素数量无限,但如果偏序关系的复杂度有限,序维度可以是有限的。 167 | - 相反,即使元素数量有限,如果偏序关系非常复杂,序维度也可能较高。 168 | 169 | - **在实际应用中的意义:** 170 | 171 | - **在数据排序、并行处理、调度等领域,了解偏序集合的序维度有助于优化算法和数据结构。** 172 | 173 | - **进一步阅读:** 174 | 175 | - **Trotter, W. T. (1992).** *Combinatorics and partially ordered sets: Dimension theory*. Johns Hopkins University Press. 176 | - **有关偏序集合、序维度和线性扩展的更多信息,可以参考组合数学和序理论的相关教材和论文。** 177 | 178 | --- 179 | 180 | 希望以上解释能够帮助您理解无限偏序集合序维度为2的例子和相关原理。 181 | -------------------------------------------------------------------------------- /tips/math/order-dimension/order-dimension@math.md: -------------------------------------------------------------------------------- 1 | - **Order dimension** Dimension of Partially Ordered Set 2 | https://en.wikipedia.org/wiki/Order_dimension 3 | - The dimension of a poset P is the least integer t for which there exists a family 4 | ${\mathcal {R}}=(<_{1},\dots ,<_{t})$ 5 | of linear extensions of P so that, for every x and y in P, x precedes y in P if and only if it precedes y in all of the linear extensions, if any such t exists. That is, 6 | $P=\bigcap {\mathcal {R}}=\bigcap _{i=1}^{t}<_{i}.$ 7 | An alternative definition of order dimension is the minimal number of total orders such that P embeds into their product with componentwise ordering i.e. $x\leq y$ if and only if $x_{i}\leq y_{i}$ for all i 8 | - **Linear extension** 9 | a linear extension of a partial order is a total order (or linear order) that is compatible with the partial order. 10 | Given any partial orders $\leq$ and $\leq ^{*}$ on a set $X,$ $\leq ^{*}$ is a linear extension of $\leq$ exactly when 11 | - $\leq ^{*}$ is a total order, and 12 | For every $x,y\in X,$ if $x\leq y,$ then $x\leq ^{*}y.$ 13 | - **狄尔沃斯定理** 14 | https://zh.wikipedia.org/zh-hans/狄尔沃斯定理 15 | Sperner 定理和 Dilworth 定理表明: 一个偏序集合的序维度至少等于其最大反链的大小。 16 | - 17 | - 18 | - **Example of dimensions of infinite set** 19 | - [[infinite-poset-2d@math@order-dimension]] 20 | - [[infinite-poset-3d@math@order-dimension]] 21 | - [[infinite-poset-4d@math@order-dimension]] #read 22 | - 23 | - 标准例(Standard Example)或称为Sn是序理论中一个重要的概念,用于证明偏序集合序维度的下限。其主要特征如下: 24 | https://en.wikipedia.org/wiki/Order_dimension#Example 25 | https://en.wikipedia.org/wiki/Crown_graph #read 26 | - 组成: 27 | - 2n个元素:a1, a2, ..., an 和 b1, b2, ..., bn 28 | - 偏序关系: 29 | - 对每个i,ai < bi 30 | - 当i ≠ j时,ai与bj不可比较 31 | - 序维度为 *n*: 32 | - Sn的序维度恰好为n 33 | - 在标准例中,任何 𝑛 个元素的反链(元素两两不可比较)都存在,因而需要至少 𝑛  个线性扩展来表示其偏序关系。#read 34 | - 35 | - 36 | - **Reference** 37 | - https://en.wikipedia.org/wiki/Order_theory -------------------------------------------------------------------------------- /tips/mdbook/mdbook.md: -------------------------------------------------------------------------------- 1 | - https://rust-lang.github.io/mdBook/ 2 | - #install `cargo install mdbook` 3 | - #usage `mdbook build` `mdbook serve` 4 | - 5 | - Add tags: https://crates.io/crates/mdbook-tagger 6 | - add giscus comment: https://sakaketsukihana.github.io/Notes/mdBook-and-Giscus.html 7 | - convert to latex and pdf: https://github.com/lbeckman314/mdbook-latex 8 | - mathjax support: https://rust-lang.github.io/mdBook/format/mathjax.html 9 | - > **Note:** The usual delimiters MathJax uses are not yet supported. You can't currently use `$$ ... $$` as delimiters and the `\[ ... \]` delimiters need an extra backslash to work. Hopefully this limitation will be lifted soon. 10 | - > **Note:** When you use double backslashes in MathJax blocks (for example in commands such as `\begin{cases} \frac 1 2 \\ \frac 3 4 \end{cases}`) you need to add *two extra* backslashes (e.g., `\begin{cases} \frac 1 2 \\\\ \frac 3 4 \end{cases}`). 11 | - My mdbook building github-action 12 | https://github.com/drmingdrmer/mdbook-full/ 13 | - My svgbob fork: 14 | svgbob renders ascii graph into svg. 15 | mdbook-svgbob adopt svgbob in mdbook 16 | https://github.com/drmingdrmer/mdbook-svgbob/ 17 | - -------------------------------------------------------------------------------- /tips/n 节点 binary-tree 的个数.md: -------------------------------------------------------------------------------- 1 | tags:: tips, math, math-combinatorics, catalan-number, binary-tree 2 | 3 | 4 | 假设有n个节点 binary-tree 共有 $C_n$ 种, 5 | 对于所有左右子树分别是i个节点和n-i个节点的 binary-tree, 共有 $C_{i} \times C_{n-i}$ 种. 6 | 7 | ![](../assets/binary-tree-count/left-right-sub-tree.excalidraw.png) 8 | 9 | 于是得到递推式: $C_{n+1} = C_0 C_{n} + C_1 C_{n-1} + ... + C_n C_0$ 10 | 11 | 符合这个递推式的一定是一个 [Catalan-number](./Catalan%20number%20卡塔兰数.md), 👈 文中给出了 Catalan 的通项公式为: 12 | 13 | $$ 14 | C_n = \frac{1}{n+1} {2n \choose n} 15 | $$ 16 | 17 | **例如**, 3节点的 binary-tree 有 $6!/3!/3!/(3+1)$ 共5种: 18 | 19 | 20 | 21 | 26 | 27 | ![](../assets/binary-tree-count/3-node-binary-trees.excalidraw.png) 28 | -------------------------------------------------------------------------------- /tips/openssl/openssl.md: -------------------------------------------------------------------------------- 1 | - RSA 2 | create rsa private key: 3 | ``` 4 | openssl genrsa -out rsa-private-key.pem 2048 5 | ``` 6 | 7 | display rsa private key: 8 | ``` 9 | openssl rsa -in rsa-private-key.pem -text -noout 10 | ``` 11 | - Create self signed key 12 | ``` 13 | openssl genrsa -des3 -passout pass:x -out server.pass.key 2048 14 | openssl rsa -passin pass:x -in server.pass.key -out server.key 15 | # writing RSA key 16 | rm server.pass.key 17 | openssl req -new -key server.key -out server.csr 18 | openssl x509 -req -days 365 -in server.csr -signkey server.key -out server.crt 19 | ``` 20 | - 21 | - Specify password: 22 | ``` 23 | openssl aes-256-cbc -in some_file.enc -out some_file.unenc -d -pass pass:somepassword 24 | openssl aes-256-cbc -in some_file.enc -out some_file.unenc -k somepassword 25 | 26 | -pass: 27 | env:somevar to get the password from an environment variable 28 | file:somepathname to get the password from the first line of the file at location pathname 29 | fd:number to get the password from the file descriptor number. 30 | stdin to read from standard input 31 | 32 | ``` 33 | - Benchmark speed: 34 | ``` 35 | openssl speed des-ede3 36 | 37 | ``` -------------------------------------------------------------------------------- /tips/raft/Inconsistent partial order pseudo time in Raft.md: -------------------------------------------------------------------------------- 1 | # Inconsistent partial order pseudo time in Raft 2 | 3 | In Raft, the pseudo time `T: (term: u64, voted_for: Option)` is 4 | partially ordered. This means that within the same term, if a node has already 5 | accepted Candidate A, it cannot accept Candidate B(handling ReqeustVote RPC): 6 | 7 | `(term=1, voted_for=Some(A)) ≯ (term=1, voted_for=Some(B))` 8 | 9 | However, once Candidate A finishes the election and a quorum accepts it, the 10 | pseudo time `T` of A becomes greater(handling AppendEntries RPC): 11 | 12 | `(term=1, voted_for=Some(A)) > (term=1, voted_for=Some(B))` 13 | 14 | As you can see, the order of `T` is inconsistent, which is problematic. This 15 | rule is often overlooked in Raft. To clarify, we can embed the `quorum_accepted` 16 | status into the pseudo time, forming: 17 | 18 | `T': (term: u64, voted_for: Option, quorum_accepted: bool)`. 19 | 20 | This adjustment ensures that the partial order of pseudo time `T'` is always 21 | consistent. And quorum accepted `T'` become totally ordered: 22 | 23 | `T'₁ > T'₂`, `T'₁ == T'₂`, or `T'₁ < T'₂`. 24 | -------------------------------------------------------------------------------- /tips/rust/Rust String tips.md: -------------------------------------------------------------------------------- 1 | tags:: tips, rust-programming, string 2 | 3 | - un-indents multiline string at compile time with crate `indoc`: 4 | https://docs.rs/indoc/latest/indoc/ 5 | ```rust 6 | use indoc::indoc; 7 | 8 | fn main() { 9 | let testing = indoc! {" 10 | def hello(): 11 | print('Hello, world!') 12 | 13 | hello() 14 | "}; 15 | let expected = "def hello():\n print('Hello, world!')\n\nhello()\n"; 16 | assert_eq!(testing, expected); 17 | } 18 | ``` -------------------------------------------------------------------------------- /tips/rust/Rust precise capture in impl Trait.md: -------------------------------------------------------------------------------- 1 | tags:: tips, rust-programming, trait, capture 2 | 3 | 4 | Rust 1.82.0 以前, 5 | 这种一个return position Trait 捕捉多个lifetime是无法实现的, 6 | 例如有了&self再捕捉别的引用的Future整不了: 7 | 8 | ```rust 9 | #[derive(Debug)] 10 | struct Foo; 11 | 12 | impl Foo { 13 | fn echo<'a, 'v>(&'a self, val: &'v str) -> impl Future + 'v { 14 | async move { 15 | println!("{}: {:?}", val, self); 16 | } 17 | } 18 | } 19 | ``` 20 | 21 | `impl Future` 后面不论是 `+'v` 还是 `+'a` 都不行, 22 | 因为实际上a和v是没有outlive关系的. 23 | 24 | 然后现在可以了, 1.82 以后, 可以使用`use`: 25 | 26 | ```rust 27 | impl Foo { 28 | fn echo<'a, 'v>(&'a self, val: &'v str) -> impl Future + use<'v, 'a> {} 29 | } 30 | ``` 31 | https://play.rust-lang.org/?version=stable&mode=debug&edition=2021&gist=eaff31898429b430092ee7a3e1009c4b 32 | 33 | 34 | Precise capturing `use<..>` syntax: 35 | https://blog.rust-lang.org/2024/10/17/Rust-1.82.0.html#precise-capturing-use-syntax 36 | 37 | ```text 38 | //@ edition: 2021 39 | fn f(x: &()) -> impl Sized { x } 40 | ``` 41 | 42 | ```text 43 | error[E0700]: hidden type for `impl Sized` captures lifetime that does not appear in bounds 44 | --> src/main.rs:1:30 45 | | 46 | 1 | fn f(x: &()) -> impl Sized { x } 47 | | --- ---------- ^ 48 | | | | 49 | | | opaque type defined here 50 | | hidden type `&()` captures the anonymous lifetime defined here 51 | | 52 | help: add a `use<...>` bound to explicitly capture `'_` 53 | | 54 | 1 | fn f(x: &()) -> impl Sized + use<'_> { x } 55 | | +++++++++ 56 | ``` 57 | -------------------------------------------------------------------------------- /tips/rust/Rust sealed trait method.md: -------------------------------------------------------------------------------- 1 | tags:: tips, rust-programming, trait, seal 2 | 3 | 4 | 5 | Rust 中的**部分可实现** Trait 6 | 7 | 允许用户实现 public trait,但某些方法可能已有默认实现且不允许被覆盖。这种设计有两个主要目的: 8 | 9 | 1. 用户专注实现核心功能 10 | 2. 系统在用户实现的基础上提供安全封装 11 | 12 | 示例代码: [non-implementable-trait-method.rs](../../rust-playground/src/bin/non-implementable-trait-method.rs) 13 | 14 | 实现机制 15 | 16 | Rust 使用 sealed trait 技巧来实现这一功能。以下是具体实现方法: 17 | 18 | 1. 定义公共 trait 和私有 sealed trait 19 | 20 | ```rust 21 | pub trait Trait { 22 | fn unimplementable(&self) 23 | where Self: sealed::Sealed 24 | { 25 | self.user_impl_this(); 26 | } 27 | 28 | fn user_impl_this(&self); 29 | } 30 | 31 | mod sealed { 32 | pub trait Sealed {} 33 | impl Sealed for T {} 34 | } 35 | ``` 36 | 37 | 这里,`Trait` 包含两个方法: 38 | 39 | - `user_impl_this`:用户需要实现的方法 40 | - `unimplementable`:用户无法覆盖的方法 41 | 42 | 2. 用户实现 43 | 44 | ```rust 45 | pub struct Implementor; 46 | 47 | impl foo::Trait for Implementor { 48 | fn user_impl_this(&self) { 49 | println!("user_impl_this"); 50 | } 51 | } 52 | ``` 53 | 54 | 用户只能实现 `user_impl_this` 方法,无法修改 `unimplementable` 方法。 55 | 56 | 工作原理 57 | 58 | - `sealed::Sealed` trait 是私有的,用户无法在外部引用它。 59 | - `unimplementable` 方法要引用 `sealed::Sealed`,因此用户无法实现这个方法。 60 | 用户试图实现 `unimplementable` 方法时,会因无法访问私有的 `sealed` 模块而失败。 61 | - 系统为所有类型实现了 `Sealed`,使 `unimplementable` 方法可用。 62 | -------------------------------------------------------------------------------- /tips/rust/Rust 中 static BoxStream 丢失信息导致 higher rank lifetime error.md: -------------------------------------------------------------------------------- 1 | tags:: tips, rust-programming, lifetime, boxstream 2 | 3 | 错误: 4 | ```text 5 | error: higher-ranked lifetime error 6 | --> src/bin/box-stream-to-impl-void-lifetime-error.rs:28:5 7 | | 8 | 28 | / async move { 9 | 29 | | stream_snapshot(strm).await; 10 | 30 | | } 11 | | |_____^ 12 | 13 | ``` 14 | 15 | [box-stream-to-impl-void-lifetime-error.rs](../../rust-playground/src/bin/box-stream-to-impl-void-lifetime-error.rs) 16 | 17 | 18 | After impl Void for `Pin>`, the error changes to 19 | 20 | [box-stream-to-impl-void-error-2.rs](../../rust-playground/src/bin/box-stream-to-impl-void-error-2.rs) 21 | 22 | online: 23 | https://play.rust-lang.org/?version=stable&mode=debug&edition=2021&gist=8c382b5a6d932aaf81815f3825efd5ed 24 | -------------------------------------------------------------------------------- /tips/rust/Rust 利用 autoref 实现 specialization.md: -------------------------------------------------------------------------------- 1 | tags:: tips, rust-programming, specialization, autoref 2 | 3 | `#[feature(specialization)]` 和 `#[feature(min_specialization)]` 还没stablize, 4 | 如果一个类型 `T` 需要根据它实现了哪些 trait 来做分发, 可以利用 Rust 中的 autoref 特性来实现. 5 | 6 | 例如下面的 `trait Echo {fn echo(&self)}` 依次匹配以下规则, 调用最先匹配到的: 7 | - 如果 `T` 是 `u64` 类型, 打印: `u64: xx`, 8 | - 如果 `T` 实现了 `Debug` 的类型, 打印: `Debug: xx`, 9 | - 对其他类型的 `T`, 只打印: `generic` 10 | 11 | 我们无法直接对 `T` 实现 specialization 特性, 但可以给它的一个 wrapper `Echoable(T)` 实现: 12 | 13 | [specialization-with-autoref.rs](../rust-playground/src/bin/specialization-with-autoref.rs) 14 | 15 | ```rust 16 | trait Echo { fn echo(&self); } 17 | 18 | struct Echoable(T); 19 | 20 | impl Echo for &&Echoable { fn echo(&self) { println!("u64: {}", self.0); } } 21 | impl Echo for &Echoable { fn echo(&self) { println!("Debug: {:?}", self.0); } } 22 | impl Echo for Echoable { fn echo(&self) { println!("generic"); } } 23 | 24 | fn main() { 25 | struct Foo; 26 | 27 | (&&&Echoable(Foo) ).echo(); // generic 28 | (&&&Echoable("str")).echo(); // Debug: "str" 29 | (&&&Echoable(1u64) ).echo(); // u64: 1 30 | ( &&Echoable(1u64) ).echo(); // Debug: 1 31 | ( &Echoable(1u64) ).echo(); // generic 32 | } 33 | ``` 34 | 35 | - 上面代码中, 使用 `Echoable` 做为一个 wrapper 为 `T` 实现支持 `specialization` 的 `Echo` trait; 36 | - 当使用 `&&&Echoable(T).echo()` 时, 当前类型如果实现了 `Echo` trait, 37 | 则调用对应的 `echo()` 方法, 否则去掉一个 `&` 继续查找, 直到找到或报错. 38 | 39 | 40 | 参考: 41 | - Generalized Autoref-Based Specialization: https://lukaskalbertodt.github.io/2019/12/05/generalized-autoref-based-specialization.html 42 | - Autoref-based stable specialization https://github.com/dtolnay/case-studies/tree/master/autoref-specialization#realistic-application 43 | 44 | 45 | 46 | 47 | -------------------------------------------------------------------------------- /tips/rust/rust-learn/rust-learn.md: -------------------------------------------------------------------------------- 1 | - Explain async, build a simple runtime 2 | https://github.com/rust-lang/async-book -------------------------------------------------------------------------------- /tips/rust/rust.md: -------------------------------------------------------------------------------- 1 | ### Categories 2 | - [[rust-useful-crate]] 3 | - [[rust-programming]] 4 | - [[rust-search-engine]] 5 | - [[rust-serialization]] 6 | - [[mdbook]] 7 | - [[rust-learn]] 8 | - 9 | - **tokio**: 10 | - https://tony612.github.io/tokio-internals/01.html 11 | - [Runtime-agnostic cooperative task scheduling budget](https://internals.rust-lang.org/t/runtime-agnostic-cooperative-task-scheduling-budget/18796) 12 | - Reducing tail latencies with automatic cooperative task yielding 13 | https://tokio.rs/blog/2020-04-preemption 14 | - 15 | - **cargo config** 16 | https://doc.rust-lang.org/cargo/reference/config.html 17 | - [[Rust 如何定义错误]] 18 | - https://docs.rs/plotters/latest/plotters/ 19 | - 20 | - serde dyn Trait trait object: 21 | https://github.com/dtolnay/typetag 22 | - 23 | - **hyperbridge** Fast multi-producer, multi-consumer unbounded channel with async support. 24 | https://github.com/singaraiona/hyperbridge 25 | - 26 | - 27 | - Add katex math to docs.rs 28 | https://github.com/drmingdrmer/math-in-rust-doc 29 | https://docs.rs/katex-doc/latest/katex_doc/ 30 | https://stackoverflow.com/questions/46495063/how-to-write-math-formulas-for-rust-documentation 31 | - 32 | - tokio doc 33 | - https://docs.rs/tokio/latest/tokio/#cpu-bound-tasks-and-blocking-code 34 | - https://tokio.rs/tokio/topics/bridging 35 | - 36 | - ### error-stack 37 | - https://github.com/datafuselabs/databend/issues/15741 38 | - https://zhuanlan.zhihu.com/p/696420829 39 | - https://crates.io/crates/error-stack 40 | - https://docs.rs/error-stack/0.4.1/error_stack/trait.ResultExt.html#tymethod.change_context 41 | - https://hash.dev/blog/announcing-error-stack 42 | - https://rust-lang.github.io/rfcs/3192-dyno.html? 43 | - 44 | - ### log crate 45 | - https://docs.rs/log/0.4.21/log/ 46 | - https://docs.rs/log/0.4.21/log/kv/index.html 47 | - 48 | - 49 | - 把 Rust 当作(伪)脚本用。 50 | - #!/bin/sh 51 | #![allow(unused_attributes)] /* 52 | OUT=/tmp/tmp && rustc "$0" -o ${OUT} && exec ${OUT} $@ || exit $? #*/ 53 | 54 | use std::process::Command; 55 | use std::io::Result; 56 | use std::path::PathBuf; 57 | use std::fs; 58 | 59 | fn mkdir(dir_name: &str) -> Result<()> { 60 | fs::create_dir(dir_name) 61 | } 62 | 63 | fn main() { 64 | println!("hello"); 65 | } 66 | - 重点是前三行。写的很巧妙,既是合法的 rust 语法,又是合法的 shell 语法。 67 | 第一行 shebang 指定了用 sh 执行该脚本,而 rustc 本身也会忽略 shebang 行,没啥好说的。 68 | 第二行声明了 rust 的一个内部属性,因为语法是 `#` 开头,所以刚好也是 shell 语法的注释行。结尾用了 rust 的多行注释,完全忽略第三行。 69 | 而 shell 免疫 rust 的多行注释,所以第三行正常执行。其实就是用 rustc 编译当前文件到二进制程序再执行并退出。 70 | 剩下的部分就是 rust 的逻辑了。 71 | - 作者:无色明天 72 | 链接:https://www.zhihu.com/question/282113351/answer/3622421263 73 | 来源:知乎 74 | 著作权归作者所有。商业转载请联系作者获得授权,非商业转载请注明出处。 -------------------------------------------------------------------------------- /tips/web-page-building/web-page-building.md: -------------------------------------------------------------------------------- 1 | - Rapidly build modern websites without ever leaving your HTML. 2 | A utility-first CSS framework packed with classes like flex, pt-4, text-center and rotate-90 that can be composed to build any design, directly in your markup. 3 | https://tailwindcss.com/ 4 | - 5 | - 6 | - [[Tailwindcss colors]] -------------------------------------------------------------------------------- /tips/为 排序字符串 创建 range filter.md: -------------------------------------------------------------------------------- 1 | tags:: tips, binary-tree, catalan-number, filter, succinct 2 | 3 | 为一组排序的字符串创建一个 range filter, 能检查输入key是否**可能存在**, 如果存在, 给出其在排序字符串集合中的什么位置; 尽可能小. 4 | 5 | 将 n 个排序字符串的 filter 要存储的信息分成3部分: **确定排序关系的关键bit**, **前缀部分**和**后缀部分**: 6 | 7 | **第1部分: 存储决定先后顺序的关键 bits**: 8 | 假设有 4 个排好序的 bit 字符串, 9 | 只考虑决定他们之间先后顺序的 **关键bit**, 10 | 即去掉公共前缀如 `A...`, `B...`, `C...` 和 后缀 `...` 之后, 下图中剩下的 0和1, 就是 **关键bit**: 11 | 12 | ``` 13 | A... 0 B... 0 ... ---> 00.. 14 | A... 0 B... 1 C... 0 ... ---> 010. 15 | A... 0 B... 1 C... 1 ... ---> 011. 16 | A... 1 ... ---> 1... 17 | ``` 18 | 19 | 其中每次相邻2行上 0/1 的变化, 都将一组字符串拆分成上下两部分. 20 | 这几个 0/1 的变化, 直接映射到一个 3 节点 bianry-tree. 21 | 即, **n 个排序串的一种关键bit的排列方式对应一个 n-1 节点的 binary-tree**. 22 | 下面列出了4个排序串所有可能的 **关键bit** 排列方式, 以及对应的 binary-tree: 23 | 24 | ![](../assets/sorted-strings-range-filter/str-demo.excalidraw.png) 25 | 26 | 因为 [存储 n 个节点的 binary-tree 只需 2n 个bit](./存储%20n%20节点的%20binary-tree%20最少只需%202n%20bit.md). 27 | 所以存储这些 **关键bit** 的空间开销是 `2(n-1)` bit. 28 | 29 | **第2部分: 存储前缀**, 如`A...`, `B...`等, 30 | 因为每个 binary-tree 的节点对应一个前缀, 31 | 我们将其存储到一个变长字符串的数组中. 32 | 假设前缀平均长度为 k 个 bit, 前缀部分存储占 `k*n` bit. 33 | 34 | **第3部分: 存储后缀**, 即那些与字符串排序完全无关的部分 `...`, 35 | 可以选择存储全量的后缀, 部分后缀或完全不存储后缀, 取决于对查询的 false 36 | positive rate 的要求. 37 | -------------------------------------------------------------------------------- /tips/使用正态分布近似计算组合数.md: -------------------------------------------------------------------------------- 1 | tags:: tips, math, binomial-distribution, normal-distribution, approximation 2 | 3 | 4 | [二项式分布](https://zh.wikipedia.org/wiki/%E4%BA%8C%E9%A0%85%E5%BC%8F%E5%88%86%E5%B8%83)可以近似为[正态分布](https://zh.wikipedia.org/wiki/%E6%AD%A3%E6%80%81%E5%88%86%E5%B8%83), 所以组合数 `C(n, m)` 也可以用正态来近似计算, 5 | 我用这种方法在工程设计阶段做快速的数值估算, 挺方便的: 6 | 7 | 例如要计算12 盘 [RAID-6](https://zh.wikipedia.org/wiki/RAID) 的数据丢失风险(2块冗余盘所以掉3盘会丢数据:`C(12, 3)`), 8 | 或设计hash table时估算一个bucket中刚好存储了`i`个key的概率: $p(i) = {n \choose i} ( \frac{1}{b} )^{ i } ( 1 - \frac{1}{b} )^{n-i}$(`n`是key总数, `b`是bucket总数) 9 | 10 | ![foo](../assets/approx-combination/binomial-normal-margin.png) 11 | 12 | ```python 13 | import math 14 | 15 | def facto(n): 16 | if n == 1: 17 | return 1 18 | return n*facto(n-1) 19 | 20 | def combi(n, m): 21 | return facto(n) / facto(m) / facto(n-m) 22 | 23 | def approx_combi(n, m): 24 | u = n * .5 25 | sig = (n*.5*.5) ** 0.5 26 | 27 | power = - (m-u) ** 2 / 2 / sig / sig 28 | return 1.0 / (sig * ((2*math.pi)**.5)) * (math.e ** power) * (2**n) 29 | 30 | n, m = 12, 3 31 | print("Approximate combination number C({}, {}) by normal distribution:".format(n, m)) 32 | print("accurate, approximated:") 33 | print(combi(n, m), '%.3f' % approx_combi(n, m)) 34 | ``` 35 | 36 | [approx-combination.py](../assets/approx-combination/approx-combination.py) 37 | 38 | Output: 39 | 40 | ``` 41 | Approximate combination number C(12, 3) by normal distribution: 42 | 43 | accurate, approximated: 44 | 220.0 210.508 45 | ``` 46 | -------------------------------------------------------------------------------- /tips/圆偏振光3d眼镜.md: -------------------------------------------------------------------------------- 1 | tags:: tips, physics, polarize, circular-polarize, 3d 2 | 3 | linear polarization 线偏振光在一个方向震动. 它可以拆分成互相垂直的, 振幅为 $\sqrt{1/2}$ 的2个线偏振光 x, y. 4 | 5 | [1/4波片](https://zh.wikipedia.org/wiki/%E6%B3%A2%E7%89%87)可将一个方向上(例如x)的偏振光减少1/4相位, 从而使得x,y的叠加形成圆形轨迹, 即[圆偏振光](https://zh.wikipedia.org/wiki/%E5%81%8F%E6%8C%AF). 6 | 7 | 圆偏振光分左旋和右旋. 8 | 9 | 圆偏振光可分解为垂直的, 和x,y无关的2组线偏振光(u,v), 即u与x可以成任意角度. 10 | 11 | 左旋圆偏振光再次通过方向为u的1/4波片时, 还原为u,v夹角45度的线偏振光 o1. 12 | 13 | 右旋圆偏振光通过同样1/4波片时, 还原为与o1垂直的线偏振光o2. 14 | 15 | 所以3d电影的原理是: 同时将左旋和右旋圆偏振光投影到屏幕上成左右眼的画面, 16 | 左眼镜片为向上的1/4波片和向左偏振镜片, 17 | 右眼镜片为向上的1/4波片和向右偏振镜片. 18 | 19 | 20 | 21 | 22 | 23 | 偏振: 24 | 25 | https://zh.wikipedia.org/wiki/%E5%81%8F%E6%8C%AF 26 | -------------------------------------------------------------------------------- /tips/存储 n 节点的 binary-tree 最少只需 2n bit.md: -------------------------------------------------------------------------------- 1 | tags:: tips, math, math-combinatorics, catalan-number, binary-tree 2 | 3 | 4 | **原理**: 5 | [n 节点 binary-tree 的个数](./n%20节点%20binary-tree%20的个数.md) 有 $C_n = \frac{1}{n+1} {2n \choose n}$ 个, 6 | 那么最节省空间的存储 binary-tree 的方法就是: 7 | **枚举所有 n 个节点的 binary-tree, 然后只存储 binary-tree 的编号**. 8 | 因此表示编号所需的 bit 数, 就是存储一个 binary-tree 的理论上最小的空间开销, 即: 9 | 10 | $$ 11 | log_2 C_n = log_2 ((2n)!) - 2 log_2 (n!) - log_2 (n+1) 12 | $$ 13 | 14 | 通过 [Stirling Approximation](https://en.wikipedia.org/wiki/Stirling%27s_approximation), 近似阶乘的计算后: 15 | 16 | $$ 17 | log_2 C_n = 2n + o(n) 18 | $$ 19 | 20 | 21 | 这表示理论上我们用 `2n` 个 bit 就可以存储任意一个 n 节点的 binary-tree. 22 | 23 | **实现**: 要达到这样的空间开销, 一种实际可行的方法是按照 `node, node.left_child, node.right_child` 的顺序将节点编码到一个`2n+1` bit 的数组中: 24 | 25 | ``` 26 | fn encode(output: &mut Vec, node) { 27 | if node.is_null() { 28 | output.push(0); 29 | } else { 30 | output.push(1); 31 | encode(output, node.left); 32 | encode(output, node.rigth); 33 | } 34 | } 35 | ``` 36 | 37 | 例如用`*` 表示树的节点, `x`表示null, 3节点 binary-tree 被编码为长度为7的bit数组(忽略括号): 38 | 39 | ``` 40 | * 41 | / \ 42 | * * ---> 1 (1 (0) (0)) (1 (0) (0)) 43 | / \ / \ 44 | x x x x 45 | 46 | * 47 | / \ 48 | * x ---> 1 (1 (0) (1 (0) (0))) (0) 49 | / \ 50 | x * 51 | / \ 52 | x x 53 | ``` 54 | 55 | 56 | 79 | 80 | 102 | -------------------------------------------------------------------------------- /tips/微信公众号.md: -------------------------------------------------------------------------------- 1 | - 在互联网信息内容主管部门的指导下,为加强帐号管理,自2018年11月16日起,进行注册上限调整: 2 | 1、同一个邮箱只能申请1个公众号; 3 | 2、同一个手机号码可绑定5个公众号; 4 | 3、同一身份证注册个人类型公众号数量上限为1个; 5 | 4、同一企业、个体工商户、其他组织资料注册公众号数量上限为2个; 6 | 5、同一政府、媒体类型可注册和认证50个公众号; 7 | 6、同一境外主体注册公众号数量上限为1个。 8 | - -------------------------------------------------------------------------------- /tips/语言改变命运.md: -------------------------------------------------------------------------------- 1 | tags:: tips, philosophy 2 | 3 | 4 | 当你谈论平等的时候,你在谈论什么? 5 | 原文: https://card.weibo.com/article/m/show/id/2309404848530983616543 6 | 7 | **语言改变思想。思想指引行动。行动固化成行为模式,行为模式塑造了你的命运。** 8 | 9 | ------ 10 | > 提问:布老师,我去年硕士毕业,开始工作。我本来想寒窗苦读十几年,终于毕业了,可以在大城市施展抱负,从来没想过要回到老家。但是因为去年的就业情况很差,我不得已听了家里人的话,考入了体制内。但是令我无法忍受的是,我因为没有背景,所以好的岗位都轮不到我。我被分配到一个省里比较偏远的地方。这里不仅交通不便,生活条件不好,就连工作也是简单的重复,得不到任何锻炼,看不到什么希望。感觉这里不是长久之计,但是也找不到出路。我感受到非常的不平等。同样是硕士毕业,前几年的师兄师姐找的工作就还不错。同样是一起进单位,有的人就被分到比较好的地方。我不知道为什么会这样。请问布老师,我该怎么做,才能有一个更好的出路? 11 | 12 | 回答:给你讲三点吧。 13 | 14 | 第一,注意你的语言。因为它就是你的命运。 15 | 16 | 怎么改变一个人的命运?很简单,改变你的语言,就能改变你的命运。简单到令人不敢相信。 17 | 18 | 因为你怎么说话,你就会怎么思考。你说话的时候,你的意识就不断地在给你的潜意识灌输想法。一句话,即使是假话,套话,胡话,你听得多了,说得多了,内心里也就信了。所以语言会改变你的想法。 19 | 20 | 孔子说:“非礼勿听”。不该听的不要听。为什么?因为你听了,即使你当时反对这个想法,它仍然会像种子一样进入你的大脑,在合适的时候就会生根发芽。听都不要听,你就不会有这个意识。没有这个意识,你就不会有这个想法。 21 | 22 | 语言会改变思想。而思想会指引行动。如果你的行动是修身正己,造福他人,那么你就会得到别人的感激和报答。如果你放任自己,为害他人,你就会得到厌弃和憎恨。而你的行为和它们的回报,则会固化成你的行为模式。你长期的行为模式挑选和塑造了周围的环境和你自己,这就是人们所说的“命运”。 23 | 24 | 所以你的语言就是你的命运。 25 | --------------------------------------------------------------------------------