├── .gitignore ├── Cargo.toml ├── LICENSE ├── README.md ├── documents ├── DeepSeek_R1.pdf ├── Moores_Law_for_Everything.pdf ├── The_Last_Question.pdf └── nightfall.pdf ├── t241225-match ├── .gitignore ├── Cargo.toml └── src │ └── main.rs ├── t241226-iter ├── .gitignore ├── Cargo.toml └── src │ └── main.rs ├── t241227-trait ├── .gitignore ├── Cargo.toml └── src │ └── main.rs ├── t241228-arc ├── .gitignore ├── Cargo.toml └── src │ └── main.rs ├── t241228-rc ├── .gitignore ├── Cargo.toml └── src │ └── main.rs ├── t241229-enum ├── .gitignore ├── Cargo.toml └── src │ └── main.rs ├── t241230-option ├── Cargo.toml └── src │ └── main.rs ├── t241231-result ├── Cargo.toml └── src │ └── main.rs ├── t250101-ownership ├── Cargo.toml └── src │ └── main.rs ├── t250102-higher-order-fun ├── Cargo.toml └── src │ └── main.rs ├── t250103-from-to ├── Cargo.toml └── src │ └── main.rs ├── t250104-question-mark ├── Cargo.toml └── src │ └── main.rs ├── t250105-slice ├── Cargo.toml └── src │ └── main.rs ├── t250106-box ├── Cargo.toml └── src │ └── main.rs ├── t250107-generic ├── Cargo.toml └── src │ └── main.rs ├── t250108-reference ├── Cargo.toml └── src │ └── main.rs ├── t250109-mpsc-channel ├── Cargo.toml └── src │ └── main.rs ├── t250110-return-fun ├── Cargo.toml └── src │ └── main.rs ├── t250111-macro ├── Cargo.toml └── src │ └── main.rs ├── t250112-arc-mutex ├── Cargo.toml └── src │ └── main.rs ├── t250113-type ├── Cargo.toml └── src │ └── main.rs ├── t250114-simple-web ├── Cargo.toml └── src │ └── main.rs ├── t250115-simple-web-with-tokio ├── Cargo.toml └── src │ └── main.rs ├── t250116-simple-web-multi-thread ├── Cargo.toml └── src │ └── main.rs ├── t250117-file-read ├── Cargo.toml └── src │ └── main.rs ├── t250118-check-digits ├── Cargo.toml └── src │ └── main.rs ├── t250119-capitalize-words ├── Cargo.toml └── src │ └── main.rs ├── t250120-move ├── Cargo.toml └── src │ └── main.rs ├── t250124-rig-gemini ├── Cargo.toml └── src │ └── main.rs ├── t250130-rag-system ├── .gitignore ├── Cargo.toml └── src │ └── main.rs ├── t250131-rig-text-classifier ├── Cargo.toml └── src │ └── main.rs ├── t250217-rig-ollama-deepseek-r1 ├── Cargo.toml └── src │ └── main.rs └── video-qr.png /.gitignore: -------------------------------------------------------------------------------- 1 | /target 2 | Cargo.lock 3 | .DS_Store 4 | .env 5 | -------------------------------------------------------------------------------- /Cargo.toml: -------------------------------------------------------------------------------- 1 | [workspace.package] 2 | name = "rust-tips" # the name of the package 3 | version = "0.1.0" # the current version, obeying semver 4 | authors = ["lispking "] # the authors of the package 5 | edition = "2021" # the edition of Rust to use 6 | license = "Apache-2.0" # the license of the package 7 | readme = "README.md" # the path to the README file 8 | description = "Rust tips" # a description of the package 9 | keywords = ["rust", "tips"] # keywords for the package 10 | categories = ["development-tools"] # categories for the package 11 | homepage = "https://github.com/lispking/rust-tips.git" 12 | repository = "https://github.com/lispking/rust-tips.git" 13 | 14 | [workspace] 15 | resolver = "2" 16 | members = [ 17 | "t241225-match", 18 | "t241226-iter", 19 | "t241227-trait", 20 | "t241228-arc", 21 | "t241228-rc", 22 | "t241229-enum", 23 | "t241230-option", 24 | "t241231-result", 25 | "t250101-ownership", 26 | "t250102-higher-order-fun", 27 | "t250103-from-to", 28 | "t250104-question-mark", 29 | "t250105-slice", 30 | "t250106-box", 31 | "t250107-generic", 32 | "t250108-reference", 33 | "t250109-mpsc-channel", 34 | "t250110-return-fun", 35 | "t250111-macro", 36 | "t250112-arc-mutex", 37 | "t250113-type", 38 | "t250114-simple-web", 39 | "t250115-simple-web-with-tokio", 40 | "t250116-simple-web-multi-thread", 41 | "t250117-file-read", 42 | "t250118-check-digits", 43 | "t250119-capitalize-words", 44 | "t250120-move", 45 | "t250124-rig-gemini", 46 | "t250130-rag-system", "t250131-rig-text-classifier", "t250217-rig-ollama-deepseek-r1", 47 | ] 48 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | Apache License 2 | Version 2.0, January 2004 3 | http://www.apache.org/licenses/ 4 | 5 | TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION 6 | 7 | 1. Definitions. 8 | 9 | "License" shall mean the terms and conditions for use, reproduction, 10 | and distribution as defined by Sections 1 through 9 of this document. 11 | 12 | "Licensor" shall mean the copyright owner or entity authorized by 13 | the copyright owner that is granting the License. 14 | 15 | "Legal Entity" shall mean the union of the acting entity and all 16 | other entities that control, are controlled by, or are under common 17 | control with that entity. For the purposes of this definition, 18 | "control" means (i) the power, direct or indirect, to cause the 19 | direction or management of such entity, whether by contract or 20 | otherwise, or (ii) ownership of fifty percent (50%) or more of the 21 | outstanding shares, or (iii) beneficial ownership of such entity. 22 | 23 | "You" (or "Your") shall mean an individual or Legal Entity 24 | exercising permissions granted by this License. 25 | 26 | "Source" form shall mean the preferred form for making modifications, 27 | including but not limited to software source code, documentation 28 | source, and configuration files. 29 | 30 | "Object" form shall mean any form resulting from mechanical 31 | transformation or translation of a Source form, including but 32 | not limited to compiled object code, generated documentation, 33 | and conversions to other media types. 34 | 35 | "Work" shall mean the work of authorship, whether in Source or 36 | Object form, made available under the License, as indicated by a 37 | copyright notice that is included in or attached to the work 38 | (an example is provided in the Appendix below). 39 | 40 | "Derivative Works" shall mean any work, whether in Source or Object 41 | form, that is based on (or derived from) the Work and for which the 42 | editorial revisions, annotations, elaborations, or other modifications 43 | represent, as a whole, an original work of authorship. For the purposes 44 | of this License, Derivative Works shall not include works that remain 45 | separable from, or merely link (or bind by name) to the interfaces of, 46 | the Work and Derivative Works thereof. 47 | 48 | "Contribution" shall mean any work of authorship, including 49 | the original version of the Work and any modifications or additions 50 | to that Work or Derivative Works thereof, that is intentionally 51 | submitted to Licensor for inclusion in the Work by the copyright owner 52 | or by an individual or Legal Entity authorized to submit on behalf of 53 | the copyright owner. For the purposes of this definition, "submitted" 54 | means any form of electronic, verbal, or written communication sent 55 | to the Licensor or its representatives, including but not limited to 56 | communication on electronic mailing lists, source code control systems, 57 | and issue tracking systems that are managed by, or on behalf of, the 58 | Licensor for the purpose of discussing and improving the Work, but 59 | excluding communication that is conspicuously marked or otherwise 60 | designated in writing by the copyright owner as "Not a Contribution." 61 | 62 | "Contributor" shall mean Licensor and any individual or Legal Entity 63 | on behalf of whom a Contribution has been received by Licensor and 64 | subsequently incorporated within the Work. 65 | 66 | 2. Grant of Copyright License. Subject to the terms and conditions of 67 | this License, each Contributor hereby grants to You a perpetual, 68 | worldwide, non-exclusive, no-charge, royalty-free, irrevocable 69 | copyright license to reproduce, prepare Derivative Works of, 70 | publicly display, publicly perform, sublicense, and distribute the 71 | Work and such Derivative Works in Source or Object form. 72 | 73 | 3. Grant of Patent License. Subject to the terms and conditions of 74 | this License, each Contributor hereby grants to You a perpetual, 75 | worldwide, non-exclusive, no-charge, royalty-free, irrevocable 76 | (except as stated in this section) patent license to make, have made, 77 | use, offer to sell, sell, import, and otherwise transfer the Work, 78 | where such license applies only to those patent claims licensable 79 | by such Contributor that are necessarily infringed by their 80 | Contribution(s) alone or by combination of their Contribution(s) 81 | with the Work to which such Contribution(s) was submitted. If You 82 | institute patent litigation against any entity (including a 83 | cross-claim or counterclaim in a lawsuit) alleging that the Work 84 | or a Contribution incorporated within the Work constitutes direct 85 | or contributory patent infringement, then any patent licenses 86 | granted to You under this License for that Work shall terminate 87 | as of the date such litigation is filed. 88 | 89 | 4. Redistribution. You may reproduce and distribute copies of the 90 | Work or Derivative Works thereof in any medium, with or without 91 | modifications, and in Source or Object form, provided that You 92 | meet the following conditions: 93 | 94 | (a) You must give any other recipients of the Work or 95 | Derivative Works a copy of this License; and 96 | 97 | (b) You must cause any modified files to carry prominent notices 98 | stating that You changed the files; and 99 | 100 | (c) You must retain, in the Source form of any Derivative Works 101 | that You distribute, all copyright, patent, trademark, and 102 | attribution notices from the Source form of the Work, 103 | excluding those notices that do not pertain to any part of 104 | the Derivative Works; and 105 | 106 | (d) If the Work includes a "NOTICE" text file as part of its 107 | distribution, then any Derivative Works that You distribute must 108 | include a readable copy of the attribution notices contained 109 | within such NOTICE file, excluding those notices that do not 110 | pertain to any part of the Derivative Works, in at least one 111 | of the following places: within a NOTICE text file distributed 112 | as part of the Derivative Works; within the Source form or 113 | documentation, if provided along with the Derivative Works; or, 114 | within a display generated by the Derivative Works, if and 115 | wherever such third-party notices normally appear. The contents 116 | of the NOTICE file are for informational purposes only and 117 | do not modify the License. You may add Your own attribution 118 | notices within Derivative Works that You distribute, alongside 119 | or as an addendum to the NOTICE text from the Work, provided 120 | that such additional attribution notices cannot be construed 121 | as modifying the License. 122 | 123 | You may add Your own copyright statement to Your modifications and 124 | may provide additional or different license terms and conditions 125 | for use, reproduction, or distribution of Your modifications, or 126 | for any such Derivative Works as a whole, provided Your use, 127 | reproduction, and distribution of the Work otherwise complies with 128 | the conditions stated in this License. 129 | 130 | 5. Submission of Contributions. Unless You explicitly state otherwise, 131 | any Contribution intentionally submitted for inclusion in the Work 132 | by You to the Licensor shall be under the terms and conditions of 133 | this License, without any additional terms or conditions. 134 | Notwithstanding the above, nothing herein shall supersede or modify 135 | the terms of any separate license agreement you may have executed 136 | with Licensor regarding such Contributions. 137 | 138 | 6. Trademarks. This License does not grant permission to use the trade 139 | names, trademarks, service marks, or product names of the Licensor, 140 | except as required for reasonable and customary use in describing the 141 | origin of the Work and reproducing the content of the NOTICE file. 142 | 143 | 7. Disclaimer of Warranty. Unless required by applicable law or 144 | agreed to in writing, Licensor provides the Work (and each 145 | Contributor provides its Contributions) on an "AS IS" BASIS, 146 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or 147 | implied, including, without limitation, any warranties or conditions 148 | of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A 149 | PARTICULAR PURPOSE. You are solely responsible for determining the 150 | appropriateness of using or redistributing the Work and assume any 151 | risks associated with Your exercise of permissions under this License. 152 | 153 | 8. Limitation of Liability. In no event and under no legal theory, 154 | whether in tort (including negligence), contract, or otherwise, 155 | unless required by applicable law (such as deliberate and grossly 156 | negligent acts) or agreed to in writing, shall any Contributor be 157 | liable to You for damages, including any direct, indirect, special, 158 | incidental, or consequential damages of any character arising as a 159 | result of this License or out of the use or inability to use the 160 | Work (including but not limited to damages for loss of goodwill, 161 | work stoppage, computer failure or malfunction, or any and all 162 | other commercial damages or losses), even if such Contributor 163 | has been advised of the possibility of such damages. 164 | 165 | 9. Accepting Warranty or Additional Liability. While redistributing 166 | the Work or Derivative Works thereof, You may choose to offer, 167 | and charge a fee for, acceptance of support, warranty, indemnity, 168 | or other liability obligations and/or rights consistent with this 169 | License. However, in accepting such obligations, You may act only 170 | on Your own behalf and on Your sole responsibility, not on behalf 171 | of any other Contributor, and only if You agree to indemnify, 172 | defend, and hold each Contributor harmless for any liability 173 | incurred by, or claims asserted against, such Contributor by reason 174 | of your accepting any such warranty or additional liability. 175 | 176 | END OF TERMS AND CONDITIONS 177 | 178 | APPENDIX: How to apply the Apache License to your work. 179 | 180 | To apply the Apache License to your work, attach the following 181 | boilerplate notice, with the fields enclosed by brackets "[]" 182 | replaced with your own identifying information. (Don't include 183 | the brackets!) The text should be enclosed in the appropriate 184 | comment syntax for the file format. We also recommend that a 185 | file or class name and description of purpose be included on the 186 | same "printed page" as the copyright notice for easier 187 | identification within third-party archives. 188 | 189 | Copyright [yyyy] [name of copyright owner] 190 | 191 | Licensed under the Apache License, Version 2.0 (the "License"); 192 | you may not use this file except in compliance with the License. 193 | You may obtain a copy of the License at 194 | 195 | http://www.apache.org/licenses/LICENSE-2.0 196 | 197 | Unless required by applicable law or agreed to in writing, software 198 | distributed under the License is distributed on an "AS IS" BASIS, 199 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 200 | See the License for the specific language governing permissions and 201 | limitations under the License. 202 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # Rust 小技巧来咯🎉 2 | 3 | 朋友们帮忙推广下呀🙏 4 | 5 | 之前我一直纠结视频号的方向,思来想去,决定深耕自己热爱的技术领域。把实用的编程知识分享出去,既能做喜欢的事,又能帮到大家,简直双赢,一起冲呀! 6 | 7 | 在这个仓库中,我将分享一些有用的 Rust 编程技巧和示例代码,希望能对大家有所帮助。欢迎大家一起学习和交流! 8 | 9 | 了解更多,请查看[探索 Rust 宝藏:每日技巧栏目上线!](https://mp.weixin.qq.com/s/1LFJC3ICw-K1mDaOS1AH_Q) 10 | 11 | 最后附上[《Web3 技术学习指南与成长助力》](https://mp.weixin.qq.com/s/aaCbNHlPmnDi1wiqzZKvzQ) 12 | 13 | 14 | ## 运行示例说明 15 | 16 | ```shell 17 | cargo r --bin=t01-match 18 | ``` 19 | 20 | ## 感谢小伙伴的 star 21 | 22 | 朋友们,如果您还没有关注视频号的话,麻烦动一动手指头帮忙关注和转发一下,谢谢 ^_^ 23 | 24 | ![视频号二维码](video-qr.png) 25 | -------------------------------------------------------------------------------- /documents/DeepSeek_R1.pdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/lispking/rust-tips/0c0968ef07b1aa5d7d9c2e84274133ef4642ad36/documents/DeepSeek_R1.pdf -------------------------------------------------------------------------------- /documents/Moores_Law_for_Everything.pdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/lispking/rust-tips/0c0968ef07b1aa5d7d9c2e84274133ef4642ad36/documents/Moores_Law_for_Everything.pdf -------------------------------------------------------------------------------- /documents/The_Last_Question.pdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/lispking/rust-tips/0c0968ef07b1aa5d7d9c2e84274133ef4642ad36/documents/The_Last_Question.pdf -------------------------------------------------------------------------------- /documents/nightfall.pdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/lispking/rust-tips/0c0968ef07b1aa5d7d9c2e84274133ef4642ad36/documents/nightfall.pdf -------------------------------------------------------------------------------- /t241225-match/.gitignore: -------------------------------------------------------------------------------- 1 | /target 2 | -------------------------------------------------------------------------------- /t241225-match/Cargo.toml: -------------------------------------------------------------------------------- 1 | [package] 2 | name = "t241225-match" 3 | version.workspace = true 4 | authors.workspace = true 5 | edition.workspace = true 6 | 7 | [dependencies] 8 | -------------------------------------------------------------------------------- /t241225-match/src/main.rs: -------------------------------------------------------------------------------- 1 | fn check_number(num: i32) { 2 | match num { 3 | 0 => println!("这是零"), 4 | 1 => println!("这是一"), 5 | 2 => println!("这是二"), 6 | _ => println!("这是其他数字"), 7 | } 8 | } 9 | 10 | fn main() { 11 | check_number(0); 12 | } 13 | -------------------------------------------------------------------------------- /t241226-iter/.gitignore: -------------------------------------------------------------------------------- 1 | /target 2 | -------------------------------------------------------------------------------- /t241226-iter/Cargo.toml: -------------------------------------------------------------------------------- 1 | [package] 2 | name = "t241226-iter" 3 | version.workspace = true 4 | authors.workspace = true 5 | edition.workspace = true 6 | 7 | [dependencies] 8 | -------------------------------------------------------------------------------- /t241226-iter/src/main.rs: -------------------------------------------------------------------------------- 1 | fn main() { 2 | let numbers = [1, 2, 3, 4, 5]; 3 | 4 | let even_numbers = numbers 5 | .iter() 6 | .filter(|&num| num % 2 == 0) 7 | .collect::>(); 8 | 9 | for num in even_numbers { 10 | println!("{} 是偶数", num); 11 | } 12 | } 13 | -------------------------------------------------------------------------------- /t241227-trait/.gitignore: -------------------------------------------------------------------------------- 1 | /target 2 | -------------------------------------------------------------------------------- /t241227-trait/Cargo.toml: -------------------------------------------------------------------------------- 1 | [package] 2 | name = "t241227-trait" 3 | version.workspace = true 4 | authors.workspace = true 5 | edition.workspace = true 6 | 7 | [dependencies] 8 | -------------------------------------------------------------------------------- /t241227-trait/src/main.rs: -------------------------------------------------------------------------------- 1 | trait Printable { 2 | fn print(&self); 3 | } 4 | 5 | struct Person { 6 | name: String, 7 | age: u8, 8 | } 9 | 10 | impl Printable for Person { 11 | fn print(&self) { 12 | println!("Name: {}, Age: {}", self.name, self.age); 13 | } 14 | } 15 | 16 | fn main() { 17 | let person = Person { 18 | name: String::from("Alice"), 19 | age: 25, 20 | }; 21 | 22 | person.print(); 23 | } 24 | -------------------------------------------------------------------------------- /t241228-arc/.gitignore: -------------------------------------------------------------------------------- 1 | /target 2 | -------------------------------------------------------------------------------- /t241228-arc/Cargo.toml: -------------------------------------------------------------------------------- 1 | [package] 2 | name = "t241228-arc" 3 | version.workspace = true 4 | authors.workspace = true 5 | edition.workspace = true 6 | 7 | [dependencies] 8 | -------------------------------------------------------------------------------- /t241228-arc/src/main.rs: -------------------------------------------------------------------------------- 1 | use std::sync::Arc; 2 | use std::thread; 3 | 4 | struct Data { 5 | value: i32, 6 | } 7 | 8 | fn main() { 9 | let shared_data = Arc::new(Data { value: 42 }); 10 | 11 | let shared_data1 = Arc::clone(&shared_data); 12 | let thread1 = thread::spawn(move || { 13 | println!("Thread 1: {}", shared_data1.value); 14 | }); 15 | 16 | let shared_data2 = Arc::clone(&shared_data); 17 | let thread2 = thread::spawn(move || { 18 | println!("Thread 2: {}", shared_data2.value); 19 | }); 20 | 21 | thread1.join().unwrap(); 22 | thread2.join().unwrap(); 23 | } 24 | -------------------------------------------------------------------------------- /t241228-rc/.gitignore: -------------------------------------------------------------------------------- 1 | /target 2 | -------------------------------------------------------------------------------- /t241228-rc/Cargo.toml: -------------------------------------------------------------------------------- 1 | [package] 2 | name = "t241228-rc" 3 | version.workspace = true 4 | authors.workspace = true 5 | edition.workspace = true 6 | 7 | [dependencies] 8 | -------------------------------------------------------------------------------- /t241228-rc/src/main.rs: -------------------------------------------------------------------------------- 1 | use std::rc::Rc; 2 | 3 | struct Data { 4 | value: i32, 5 | } 6 | 7 | fn main() { 8 | let data1 = Rc::new(Data { value: 42 }); 9 | let data2 = data1.clone(); 10 | 11 | println!("Data1 value: {}", data1.value); 12 | println!("Data2 value: {}", data2.value); 13 | } 14 | -------------------------------------------------------------------------------- /t241229-enum/.gitignore: -------------------------------------------------------------------------------- 1 | /target 2 | -------------------------------------------------------------------------------- /t241229-enum/Cargo.toml: -------------------------------------------------------------------------------- 1 | [package] 2 | name = "t241229-enum" 3 | version.workspace = true 4 | authors.workspace = true 5 | edition.workspace = true 6 | 7 | [dependencies] 8 | -------------------------------------------------------------------------------- /t241229-enum/src/main.rs: -------------------------------------------------------------------------------- 1 | enum Color { 2 | Red, 3 | Green, 4 | Blue, 5 | } 6 | 7 | fn print_color(color: Color) { 8 | match color { 9 | Color::Red => println!("这是红色"), 10 | Color::Green => println!("这是绿色"), 11 | Color::Blue => println!("这是蓝色"), 12 | } 13 | } 14 | 15 | fn main() { 16 | let my_color = Color::Green; 17 | print_color(my_color); 18 | 19 | let my_color = Color::Blue; 20 | print_color(my_color); 21 | 22 | let my_color = Color::Red; 23 | print_color(my_color); 24 | } 25 | -------------------------------------------------------------------------------- /t241230-option/Cargo.toml: -------------------------------------------------------------------------------- 1 | [package] 2 | name = "t241230-option" 3 | version.workspace = true 4 | authors.workspace = true 5 | edition.workspace = true 6 | license.workspace = true 7 | readme.workspace = true 8 | description.workspace = true 9 | keywords.workspace = true 10 | categories.workspace = true 11 | homepage.workspace = true 12 | repository.workspace = true 13 | 14 | [dependencies] 15 | -------------------------------------------------------------------------------- /t241230-option/src/main.rs: -------------------------------------------------------------------------------- 1 | fn divide(numerator: f64, denominator: f64) -> Option { 2 | if denominator == 0.0 { 3 | None 4 | } else { 5 | Some(numerator / denominator) 6 | } 7 | } 8 | 9 | fn main() { 10 | let result = divide(10.0, 2.0); 11 | match result { 12 | Some(value) => println!("结果: {}", value), 13 | None => println!("除数不能为 0"), 14 | } 15 | } 16 | -------------------------------------------------------------------------------- /t241231-result/Cargo.toml: -------------------------------------------------------------------------------- 1 | [package] 2 | name = "t241231-result" 3 | version.workspace = true 4 | authors.workspace = true 5 | edition.workspace = true 6 | license.workspace = true 7 | readme.workspace = true 8 | description.workspace = true 9 | keywords.workspace = true 10 | categories.workspace = true 11 | homepage.workspace = true 12 | repository.workspace = true 13 | 14 | [dependencies] 15 | -------------------------------------------------------------------------------- /t241231-result/src/main.rs: -------------------------------------------------------------------------------- 1 | use std::fs::File; 2 | use std::io::{Error, Read}; 3 | 4 | fn read_file(path: &str) -> Result { 5 | let mut file = File::open(path)?; 6 | let mut contents = String::new(); 7 | file.read_to_string(&mut contents)?; 8 | Ok(contents) 9 | } 10 | 11 | fn main() { 12 | match read_file("my_file.txt") { 13 | Ok(contents) => println!("文件内容: {}", contents), 14 | Err(e) => println!("错误: {}", e), 15 | } 16 | } 17 | -------------------------------------------------------------------------------- /t250101-ownership/Cargo.toml: -------------------------------------------------------------------------------- 1 | [package] 2 | name = "t250101-ownership" 3 | version.workspace = true 4 | authors.workspace = true 5 | edition.workspace = true 6 | license.workspace = true 7 | readme.workspace = true 8 | description.workspace = true 9 | keywords.workspace = true 10 | categories.workspace = true 11 | homepage.workspace = true 12 | repository.workspace = true 13 | 14 | [dependencies] 15 | -------------------------------------------------------------------------------- /t250101-ownership/src/main.rs: -------------------------------------------------------------------------------- 1 | fn print_string(value: &String) { 2 | println!("Borrowed: {}", value); 3 | } 4 | 5 | fn take_ownership(value: String) { 6 | // 这里拥有了传入值的所有权 7 | println!("Received: {}", value); 8 | } 9 | 10 | fn main() { 11 | let happy_new_year = String::from("Hello, 2025!"); 12 | print_string(&happy_new_year); 13 | // 所有权未转移,可以继续使用 happy_new_year 14 | 15 | take_ownership(happy_new_year); 16 | // 此时 happy_new_year 的所有权已转移,不能再使用 17 | } 18 | -------------------------------------------------------------------------------- /t250102-higher-order-fun/Cargo.toml: -------------------------------------------------------------------------------- 1 | [package] 2 | name = "t250102-higher-order-fun" 3 | version.workspace = true 4 | authors.workspace = true 5 | edition.workspace = true 6 | license.workspace = true 7 | readme.workspace = true 8 | description.workspace = true 9 | keywords.workspace = true 10 | categories.workspace = true 11 | homepage.workspace = true 12 | repository.workspace = true 13 | 14 | [dependencies] 15 | -------------------------------------------------------------------------------- /t250102-higher-order-fun/src/main.rs: -------------------------------------------------------------------------------- 1 | fn apply_operation(numbers: &[i32], operation: F) -> Vec 2 | where 3 | F: Fn(i32) -> i32, 4 | { 5 | numbers.iter().map(|&num| operation(num)).collect() 6 | } 7 | 8 | fn double(x: i32) -> i32 { 9 | x * 2 10 | } 11 | 12 | fn main() { 13 | let numbers = vec![1, 2, 3, 4, 5]; 14 | let result = apply_operation(&numbers, double); 15 | println!("{:?}", result); 16 | } 17 | -------------------------------------------------------------------------------- /t250103-from-to/Cargo.toml: -------------------------------------------------------------------------------- 1 | [package] 2 | name = "t250103-from-to" 3 | version.workspace = true 4 | authors.workspace = true 5 | edition.workspace = true 6 | license.workspace = true 7 | readme.workspace = true 8 | description.workspace = true 9 | keywords.workspace = true 10 | categories.workspace = true 11 | homepage.workspace = true 12 | repository.workspace = true 13 | 14 | [dependencies] 15 | -------------------------------------------------------------------------------- /t250103-from-to/src/main.rs: -------------------------------------------------------------------------------- 1 | #[derive(Debug)] 2 | struct Person { 3 | name: String, 4 | age: u32, 5 | } 6 | 7 | impl From<(String, u32)> for Person { 8 | fn from(tuple: (String, u32)) -> Self { 9 | Person { 10 | name: tuple.0, 11 | age: tuple.1, 12 | } 13 | } 14 | } 15 | 16 | impl From for (String, u32) { 17 | fn from(val: Person) -> Self { 18 | (val.name, val.age) 19 | } 20 | } 21 | 22 | fn main() { 23 | let tuple = ("Alice".to_string(), 25); 24 | let person = Person::from(tuple); 25 | println!("{:?}", person); 26 | 27 | let person = Person { 28 | name: "Bob".to_string(), 29 | age: 30, 30 | }; 31 | let tuple: (String, u32) = person.into(); 32 | println!("{:?}", tuple); 33 | } 34 | -------------------------------------------------------------------------------- /t250104-question-mark/Cargo.toml: -------------------------------------------------------------------------------- 1 | [package] 2 | name = "t250104-question-mark" 3 | version.workspace = true 4 | authors.workspace = true 5 | edition.workspace = true 6 | license.workspace = true 7 | readme.workspace = true 8 | description.workspace = true 9 | keywords.workspace = true 10 | categories.workspace = true 11 | homepage.workspace = true 12 | repository.workspace = true 13 | 14 | [dependencies] 15 | -------------------------------------------------------------------------------- /t250104-question-mark/src/main.rs: -------------------------------------------------------------------------------- 1 | use std::num::ParseIntError; 2 | 3 | fn double_and_convert(s: &str) -> Result { 4 | let num = s.parse::()?; 5 | Ok(num * 2) 6 | } 7 | 8 | fn main() { 9 | match double_and_convert("10") { 10 | Ok(result) => println!("Result: {}", result), 11 | Err(err) => println!("Error: {}", err), 12 | } 13 | } 14 | -------------------------------------------------------------------------------- /t250105-slice/Cargo.toml: -------------------------------------------------------------------------------- 1 | [package] 2 | name = "t250105-slice" 3 | version.workspace = true 4 | authors.workspace = true 5 | edition.workspace = true 6 | license.workspace = true 7 | readme.workspace = true 8 | description.workspace = true 9 | keywords.workspace = true 10 | categories.workspace = true 11 | homepage.workspace = true 12 | repository.workspace = true 13 | 14 | [dependencies] 15 | -------------------------------------------------------------------------------- /t250105-slice/src/main.rs: -------------------------------------------------------------------------------- 1 | fn main() { 2 | let numbers = [1, 2, 3, 4, 5]; 3 | 4 | // 创建一个切片 5 | let slice = &numbers[1..4]; 6 | 7 | // 遍历切片 8 | for num in slice { 9 | println!("{}", num); 10 | } 11 | 12 | // 修改切片元素(前提是原始数组是可变的) 13 | let mut mutable_numbers = [1, 2, 3, 4, 5]; 14 | println!("修改前:{:?}", mutable_numbers); 15 | let mutable_slice = &mut mutable_numbers[1..4]; 16 | mutable_slice[0] = 10; 17 | println!("修改后:{:?}", mutable_numbers); 18 | } 19 | -------------------------------------------------------------------------------- /t250106-box/Cargo.toml: -------------------------------------------------------------------------------- 1 | [package] 2 | name = "t250106-box" 3 | version.workspace = true 4 | authors.workspace = true 5 | edition.workspace = true 6 | license.workspace = true 7 | readme.workspace = true 8 | description.workspace = true 9 | keywords.workspace = true 10 | categories.workspace = true 11 | homepage.workspace = true 12 | repository.workspace = true 13 | 14 | [dependencies] 15 | -------------------------------------------------------------------------------- /t250106-box/src/main.rs: -------------------------------------------------------------------------------- 1 | trait Animal { 2 | fn make_sound(&self); 3 | } 4 | 5 | struct Dog; 6 | 7 | impl Animal for Dog { 8 | fn make_sound(&self) { 9 | println!("汪汪汪"); 10 | } 11 | } 12 | 13 | fn main() { 14 | // 使用 Box 存储动态类型 15 | let animal: Box = Box::new(Dog {}); 16 | 17 | // 调用动态类型的方法 18 | animal.make_sound(); 19 | } 20 | -------------------------------------------------------------------------------- /t250107-generic/Cargo.toml: -------------------------------------------------------------------------------- 1 | [package] 2 | name = "t250107-generic" 3 | version.workspace = true 4 | authors.workspace = true 5 | edition.workspace = true 6 | license.workspace = true 7 | readme.workspace = true 8 | description.workspace = true 9 | keywords.workspace = true 10 | categories.workspace = true 11 | homepage.workspace = true 12 | repository.workspace = true 13 | 14 | [dependencies] 15 | -------------------------------------------------------------------------------- /t250107-generic/src/main.rs: -------------------------------------------------------------------------------- 1 | struct Container { 2 | item: T, 3 | } 4 | 5 | impl Container { 6 | fn new(item: T) -> Self { 7 | Container { item } 8 | } 9 | 10 | fn get_item(&self) -> &T { 11 | &self.item 12 | } 13 | } 14 | 15 | fn main() { 16 | let int_container = Container::new(42); 17 | let string_container = Container::new("Hello"); 18 | println!( 19 | "int: {:?}, string: {:?}", 20 | int_container.get_item(), 21 | string_container.get_item() 22 | ); 23 | } 24 | -------------------------------------------------------------------------------- /t250108-reference/Cargo.toml: -------------------------------------------------------------------------------- 1 | [package] 2 | name = "t250108-reference" 3 | version.workspace = true 4 | authors.workspace = true 5 | edition.workspace = true 6 | license.workspace = true 7 | readme.workspace = true 8 | description.workspace = true 9 | keywords.workspace = true 10 | categories.workspace = true 11 | homepage.workspace = true 12 | repository.workspace = true 13 | 14 | [dependencies] 15 | -------------------------------------------------------------------------------- /t250108-reference/src/main.rs: -------------------------------------------------------------------------------- 1 | fn modify_value(num: &mut i32) { 2 | *num += 1; 3 | } 4 | 5 | fn double_value(num: &i32) -> i32 { 6 | *num * 2 7 | } 8 | 9 | fn main() { 10 | let mut number = 5; 11 | modify_value(&mut number); 12 | println!("Modified number: {}", number); 13 | 14 | let num = 3; 15 | println!("double value: {}", double_value(&num)); 16 | } 17 | -------------------------------------------------------------------------------- /t250109-mpsc-channel/Cargo.toml: -------------------------------------------------------------------------------- 1 | [package] 2 | name = "t250109-mpsc-channel" 3 | version.workspace = true 4 | authors.workspace = true 5 | edition.workspace = true 6 | license.workspace = true 7 | readme.workspace = true 8 | description.workspace = true 9 | keywords.workspace = true 10 | categories.workspace = true 11 | homepage.workspace = true 12 | repository.workspace = true 13 | 14 | [dependencies] 15 | -------------------------------------------------------------------------------- /t250109-mpsc-channel/src/main.rs: -------------------------------------------------------------------------------- 1 | use std::sync::mpsc; 2 | use std::thread; 3 | 4 | fn main() { 5 | let (tx, rx) = mpsc::channel(); 6 | 7 | thread::spawn(move || { 8 | tx.send(42).unwrap(); 9 | }); 10 | 11 | let received = rx.recv().unwrap(); 12 | println!("Received: {}", received); 13 | } 14 | -------------------------------------------------------------------------------- /t250110-return-fun/Cargo.toml: -------------------------------------------------------------------------------- 1 | [package] 2 | name = "t250110-return-fun" 3 | version.workspace = true 4 | authors.workspace = true 5 | edition.workspace = true 6 | license.workspace = true 7 | readme.workspace = true 8 | description.workspace = true 9 | keywords.workspace = true 10 | categories.workspace = true 11 | homepage.workspace = true 12 | repository.workspace = true 13 | 14 | [dependencies] 15 | -------------------------------------------------------------------------------- /t250110-return-fun/src/main.rs: -------------------------------------------------------------------------------- 1 | fn add_n(func: F) -> impl Fn(i32) -> i32 2 | where 3 | F: Fn(i32) -> i32, 4 | { 5 | move |x| func(x) 6 | } 7 | 8 | fn main() { 9 | let add_five = add_n(|x| x + 5); 10 | let result = add_five(10); 11 | println!("result: {}", result); 12 | } 13 | -------------------------------------------------------------------------------- /t250111-macro/Cargo.toml: -------------------------------------------------------------------------------- 1 | [package] 2 | name = "t250111-macro" 3 | version.workspace = true 4 | authors.workspace = true 5 | edition.workspace = true 6 | license.workspace = true 7 | readme.workspace = true 8 | description.workspace = true 9 | keywords.workspace = true 10 | categories.workspace = true 11 | homepage.workspace = true 12 | repository.workspace = true 13 | 14 | [dependencies] 15 | -------------------------------------------------------------------------------- /t250111-macro/src/main.rs: -------------------------------------------------------------------------------- 1 | macro_rules! create_fn { 2 | ($name:ident, $value:expr) => { 3 | fn $name() -> i32 { 4 | $value 5 | } 6 | }; 7 | } 8 | 9 | create_fn!(get_five, 5); 10 | create_fn!(get_ten, 10); 11 | 12 | fn main() { 13 | println!("{}", get_five()); // 输出 5 14 | println!("{}", get_ten()); // 输出 10 15 | } 16 | -------------------------------------------------------------------------------- /t250112-arc-mutex/Cargo.toml: -------------------------------------------------------------------------------- 1 | [package] 2 | name = "t250112-arc-mutex" 3 | version.workspace = true 4 | authors.workspace = true 5 | edition.workspace = true 6 | license.workspace = true 7 | readme.workspace = true 8 | description.workspace = true 9 | keywords.workspace = true 10 | categories.workspace = true 11 | homepage.workspace = true 12 | repository.workspace = true 13 | 14 | [dependencies] 15 | -------------------------------------------------------------------------------- /t250112-arc-mutex/src/main.rs: -------------------------------------------------------------------------------- 1 | use std::sync::{Arc, Mutex}; 2 | use std::thread; 3 | 4 | fn main() { 5 | // 创建一个共享的、被互斥锁保护的空Vec 6 | let shared_vec = Arc::new(Mutex::new(Vec::::new())); 7 | let mut handles = vec![]; 8 | 9 | // 创建10个线程 10 | for _ in 0..10 { 11 | let shared_vec = Arc::clone(&shared_vec); 12 | handles.push(thread::spawn(move || { 13 | shared_vec.lock().unwrap().push(1); 14 | })); 15 | } 16 | 17 | // 等待所有线程执行完毕 18 | for handle in handles { 19 | handle.join().unwrap(); 20 | } 21 | 22 | // 获取最终的共享Vec,并打印其长度(也就是元素个数) 23 | let final_vec = shared_vec.lock().unwrap(); 24 | println!("The length of the shared vector is {}", final_vec.len()); 25 | } 26 | -------------------------------------------------------------------------------- /t250113-type/Cargo.toml: -------------------------------------------------------------------------------- 1 | [package] 2 | name = "t250113-type" 3 | version.workspace = true 4 | authors.workspace = true 5 | edition.workspace = true 6 | license.workspace = true 7 | readme.workspace = true 8 | description.workspace = true 9 | keywords.workspace = true 10 | categories.workspace = true 11 | homepage.workspace = true 12 | repository.workspace = true 13 | 14 | [dependencies] 15 | -------------------------------------------------------------------------------- /t250113-type/src/main.rs: -------------------------------------------------------------------------------- 1 | // 定义货币金额的类型别名,以分为单位 2 | type CurrencyAmount = i64; 3 | // 定义利率的类型别名,精确到小数点后四位 4 | type InterestRate = f64; 5 | 6 | // 计算利息的函数 7 | fn calculate_interest(principal: CurrencyAmount, rate: InterestRate) -> CurrencyAmount { 8 | // 将金额转换为元,计算利息,再转换回分 9 | let principal_in_dollars = principal as f64 / 100.0; 10 | let interest_in_dollars = principal_in_dollars * rate; 11 | (interest_in_dollars * 100.0) as i64 12 | } 13 | 14 | fn main() { 15 | let principal: CurrencyAmount = 100000; // 1000元,以分为单位 16 | let rate: InterestRate = 0.05; // 5% 的利率 17 | let interest = calculate_interest(principal, rate); 18 | println!("计算出的利息为: {} 分", interest); 19 | } 20 | -------------------------------------------------------------------------------- /t250114-simple-web/Cargo.toml: -------------------------------------------------------------------------------- 1 | [package] 2 | name = "t250114-simple-web" 3 | version.workspace = true 4 | authors.workspace = true 5 | edition.workspace = true 6 | license.workspace = true 7 | readme.workspace = true 8 | description.workspace = true 9 | keywords.workspace = true 10 | categories.workspace = true 11 | homepage.workspace = true 12 | repository.workspace = true 13 | 14 | [dependencies] 15 | -------------------------------------------------------------------------------- /t250114-simple-web/src/main.rs: -------------------------------------------------------------------------------- 1 | use std::io::prelude::*; 2 | use std::net::TcpListener; 3 | use std::net::TcpStream; 4 | 5 | fn main() { 6 | let listener = TcpListener::bind("127.0.0.1:8080").unwrap(); 7 | println!("Web server listening on port 8080"); 8 | 9 | for stream in listener.incoming() { 10 | let stream = stream.unwrap(); 11 | handle_connection(stream); 12 | } 13 | } 14 | 15 | fn handle_connection(mut stream: TcpStream) { 16 | let response = "HTTP/1.1 200 OK\r\nContent-Length: 12\r\n\r\nHello, World!"; 17 | stream.write(response.as_bytes()).unwrap(); 18 | stream.flush().unwrap(); 19 | } 20 | -------------------------------------------------------------------------------- /t250115-simple-web-with-tokio/Cargo.toml: -------------------------------------------------------------------------------- 1 | [package] 2 | name = "t250115-simple-web-with-tokio" 3 | version.workspace = true 4 | authors.workspace = true 5 | edition.workspace = true 6 | license.workspace = true 7 | readme.workspace = true 8 | description.workspace = true 9 | keywords.workspace = true 10 | categories.workspace = true 11 | homepage.workspace = true 12 | repository.workspace = true 13 | 14 | [dependencies] 15 | tokio = { version = "1", features = ["full"] } 16 | -------------------------------------------------------------------------------- /t250115-simple-web-with-tokio/src/main.rs: -------------------------------------------------------------------------------- 1 | use tokio::{ 2 | io::AsyncWriteExt, 3 | net::{TcpListener, TcpStream}, 4 | }; 5 | 6 | #[tokio::main] 7 | async fn main() { 8 | let listener = TcpListener::bind("127.0.0.1:8080").await.unwrap(); 9 | println!("Web server listening on port 8080"); 10 | 11 | loop { 12 | let (socket, _) = listener.accept().await.unwrap(); 13 | handle_connection(socket).await; 14 | } 15 | } 16 | 17 | async fn handle_connection(mut socket: TcpStream) { 18 | let response = "HTTP/1.1 200 OK\r\nContent-Length: 12\r\n\r\nHello, World!"; 19 | let _ = socket.write_all(response.as_bytes()).await; 20 | let _ = socket.flush().await; 21 | } 22 | -------------------------------------------------------------------------------- /t250116-simple-web-multi-thread/Cargo.toml: -------------------------------------------------------------------------------- 1 | [package] 2 | name = "t250116-simple-web-multi-thread" 3 | version.workspace = true 4 | authors.workspace = true 5 | edition.workspace = true 6 | license.workspace = true 7 | readme.workspace = true 8 | description.workspace = true 9 | keywords.workspace = true 10 | categories.workspace = true 11 | homepage.workspace = true 12 | repository.workspace = true 13 | 14 | [dependencies] 15 | tokio = { version = "1", features = ["full"] } 16 | -------------------------------------------------------------------------------- /t250116-simple-web-multi-thread/src/main.rs: -------------------------------------------------------------------------------- 1 | use tokio::{ 2 | io::AsyncWriteExt, 3 | net::{TcpListener, TcpStream}, 4 | runtime::Builder, 5 | }; 6 | 7 | fn main() { 8 | // Create a runtime with a thread pool 9 | let runtime = Builder::new_multi_thread() 10 | .worker_threads(4) // Specify number of worker threads 11 | .enable_all() 12 | .build() 13 | .unwrap(); 14 | 15 | runtime.block_on(async { 16 | let listener = TcpListener::bind("127.0.0.1:8080").await.unwrap(); 17 | println!("Web server listening on port 8080"); 18 | 19 | loop { 20 | let (socket, _) = listener.accept().await.unwrap(); 21 | tokio::spawn(async move { 22 | handle_connection(socket).await; 23 | }); 24 | } 25 | }); 26 | } 27 | 28 | async fn handle_connection(mut socket: TcpStream) { 29 | let response = "HTTP/1.1 200 OK\r\nContent-Length: 12\r\n\r\nHello, World!"; 30 | let _ = socket.write_all(response.as_bytes()).await; 31 | let _ = socket.flush().await; 32 | } 33 | -------------------------------------------------------------------------------- /t250117-file-read/Cargo.toml: -------------------------------------------------------------------------------- 1 | [package] 2 | name = "t250117-file-read" 3 | version.workspace = true 4 | authors.workspace = true 5 | edition.workspace = true 6 | license.workspace = true 7 | readme.workspace = true 8 | description.workspace = true 9 | keywords.workspace = true 10 | categories.workspace = true 11 | homepage.workspace = true 12 | repository.workspace = true 13 | 14 | [dependencies] 15 | -------------------------------------------------------------------------------- /t250117-file-read/src/main.rs: -------------------------------------------------------------------------------- 1 | // use std::fs::File; 2 | // use std::io::{self, Read}; 3 | 4 | // fn main() -> io::Result<()> { 5 | // let mut file = File::open("README.md")?; 6 | // let mut contents = String::new(); 7 | // file.read_to_string(&mut contents)?; 8 | // println!("{}", contents); 9 | // Ok(()) 10 | // } 11 | 12 | use std::fs; 13 | 14 | fn main() -> Result<(), std::io::Error> { 15 | let contents = fs::read_to_string("README.md")?; 16 | println!("{}", contents); 17 | Ok(()) 18 | } 19 | -------------------------------------------------------------------------------- /t250118-check-digits/Cargo.toml: -------------------------------------------------------------------------------- 1 | [package] 2 | name = "t250118-check-digits" 3 | version.workspace = true 4 | authors.workspace = true 5 | edition.workspace = true 6 | license.workspace = true 7 | readme.workspace = true 8 | description.workspace = true 9 | keywords.workspace = true 10 | categories.workspace = true 11 | homepage.workspace = true 12 | repository.workspace = true 13 | 14 | [dependencies] 15 | -------------------------------------------------------------------------------- /t250118-check-digits/src/main.rs: -------------------------------------------------------------------------------- 1 | fn is_all_digits(s: &str) -> bool { 2 | for char in s.chars() { 3 | if !char.is_digit(10) { 4 | return false; 5 | } 6 | } 7 | true 8 | } 9 | 10 | fn is_all_digits_v2(s: &str) -> bool { 11 | s.chars().all(|char| char.is_digit(10)) 12 | } 13 | 14 | fn is_all_digits_v3(s: &str) -> bool { 15 | s.chars() 16 | .map(|c| c.is_ascii_digit() as u8) 17 | .fold(1, |acc, is_digit| acc & is_digit) 18 | == 1 19 | } 20 | 21 | fn main() { 22 | println!("is_all_digits: {}", is_all_digits("123456")); 23 | println!("is_all_digits_v2: {}", is_all_digits_v2("123456")); 24 | println!("is_all_digits_v2: {}", is_all_digits_v3("123456")); 25 | } 26 | -------------------------------------------------------------------------------- /t250119-capitalize-words/Cargo.toml: -------------------------------------------------------------------------------- 1 | [package] 2 | name = "t250119-capitalize-words" 3 | version.workspace = true 4 | authors.workspace = true 5 | edition.workspace = true 6 | license.workspace = true 7 | readme.workspace = true 8 | description.workspace = true 9 | keywords.workspace = true 10 | categories.workspace = true 11 | homepage.workspace = true 12 | repository.workspace = true 13 | 14 | [dependencies] 15 | -------------------------------------------------------------------------------- /t250119-capitalize-words/src/main.rs: -------------------------------------------------------------------------------- 1 | fn capitalize_words(s: &str) -> String { 2 | let mut result = String::new(); 3 | let mut words = s.split_whitespace(); 4 | if let Some(first_word) = words.next() { 5 | result.push_str(&first_word[0..1].to_uppercase()); 6 | result.push_str(&first_word[1..]); 7 | } 8 | for word in words { 9 | result.push(' '); 10 | result.push_str(&word[0..1].to_uppercase()); 11 | result.push_str(&word[1..]); 12 | } 13 | result 14 | } 15 | 16 | fn capitalize_wordsv2(s: &str) -> String { 17 | s.split_whitespace() 18 | .map(|word| { 19 | word.chars().next().map_or_else(String::new, |c| { 20 | format!("{}{}", c.to_uppercase(), &word[1..]) 21 | }) 22 | }) 23 | .collect::>() 24 | .join(" ") 25 | } 26 | 27 | fn main() { 28 | println!("{}", capitalize_words("hello, world!")); 29 | println!("{}", capitalize_wordsv2("hello, world!")); 30 | } 31 | -------------------------------------------------------------------------------- /t250120-move/Cargo.toml: -------------------------------------------------------------------------------- 1 | [package] 2 | name = "t250120-move" 3 | version.workspace = true 4 | authors.workspace = true 5 | edition.workspace = true 6 | license.workspace = true 7 | readme.workspace = true 8 | description.workspace = true 9 | keywords.workspace = true 10 | categories.workspace = true 11 | homepage.workspace = true 12 | repository.workspace = true 13 | 14 | [dependencies] 15 | -------------------------------------------------------------------------------- /t250120-move/src/main.rs: -------------------------------------------------------------------------------- 1 | fn main() { 2 | let my_bubble_tea = String::from("珍珠奶茶"); 3 | let friend_bubble_tea = my_bubble_tea; 4 | // println!("我想喝我的奶茶:{}", my_bubble_tea); // ^^^^^^^^^^^^^ value borrowed here after move 5 | println!("送给朋友的:{}", friend_bubble_tea); 6 | } 7 | -------------------------------------------------------------------------------- /t250124-rig-gemini/Cargo.toml: -------------------------------------------------------------------------------- 1 | [package] 2 | name = "t250124-rig-gemini" 3 | version.workspace = true 4 | authors.workspace = true 5 | edition.workspace = true 6 | license.workspace = true 7 | readme.workspace = true 8 | description.workspace = true 9 | keywords.workspace = true 10 | categories.workspace = true 11 | homepage.workspace = true 12 | repository.workspace = true 13 | 14 | [dependencies] 15 | anyhow = "1.0.95" 16 | rig-core = "0.6.1" 17 | tokio = { version = "1.34.0", features = ["full"] } 18 | -------------------------------------------------------------------------------- /t250124-rig-gemini/src/main.rs: -------------------------------------------------------------------------------- 1 | use rig::{completion::Prompt, providers}; 2 | 3 | #[tokio::main] 4 | async fn main() -> Result<(), anyhow::Error> { 5 | let client = providers::gemini::Client::from_env(); 6 | let agent = client 7 | .agent("gemini-1.5-pro") 8 | .preamble("You are a helpful assistant.") 9 | .build(); 10 | 11 | let answer = agent.prompt("Tell me a joke").await?; 12 | println!("Answer: {}", answer); 13 | Ok(()) 14 | } 15 | -------------------------------------------------------------------------------- /t250130-rag-system/.gitignore: -------------------------------------------------------------------------------- 1 | # Rust build directory 2 | /target/ 3 | 4 | # Cargo lock file (uncomment this if this is a library) 5 | # Cargo.lock 6 | 7 | # Backup files 8 | **/*.rs.bk 9 | 10 | # macOS specific files 11 | .DS_Store 12 | .AppleDouble 13 | .LSOverride 14 | 15 | # IDE specific files 16 | .idea/ 17 | .vscode/ 18 | *.swp 19 | *.swo 20 | .code-workspace 21 | 22 | # Environment files 23 | .env 24 | .env.local 25 | .env.*.local 26 | 27 | # OpenAI API key file (if you're using one) 28 | openai_key.txt 29 | 30 | # Generated embeddings or cache 31 | .cache/ 32 | embeddings/ 33 | vector_store/ 34 | 35 | # Log files 36 | *.log 37 | 38 | # PDF files in documents directory (uncomment if you don't want to track PDFs) 39 | # documents/*.pdf 40 | 41 | # Binary files 42 | *.exe 43 | *.dll 44 | *.dylib 45 | *.so 46 | 47 | # Debug files 48 | *.pdb -------------------------------------------------------------------------------- /t250130-rag-system/Cargo.toml: -------------------------------------------------------------------------------- 1 | [package] 2 | name = "t250130-rag-system" 3 | version = "0.1.0" 4 | edition = "2021" 5 | 6 | [dependencies] 7 | rig-core = { version = "0.5.0", features = ["pdf", "derive"] } 8 | tokio = { version = "1.34.0", features = ["full"] } 9 | anyhow = "1.0.75" 10 | serde = { version = "1.0", features = ["derive"] } 11 | -------------------------------------------------------------------------------- /t250130-rag-system/src/main.rs: -------------------------------------------------------------------------------- 1 | use anyhow::{Context, Result}; 2 | use rig::{ 3 | embeddings::EmbeddingsBuilder, 4 | loaders::PdfFileLoader, 5 | providers::openai::{self, TEXT_EMBEDDING_ADA_002}, 6 | vector_store::in_memory_store::InMemoryVectorStore, 7 | Embed, 8 | }; 9 | use serde::{Deserialize, Serialize}; 10 | use std::path::PathBuf; 11 | 12 | #[derive(Embed, Clone, Debug, Serialize, Deserialize, Eq, PartialEq)] 13 | struct Document { 14 | id: String, 15 | #[embed] 16 | content: String, 17 | } 18 | 19 | fn load_pdf(path: PathBuf) -> Result> { 20 | let mut chunks = Vec::new(); 21 | let mut current_chunk = String::new(); 22 | let chunk_size = 2000; // Approximately 2000 characters per chunk 23 | 24 | for entry in PdfFileLoader::with_glob(path.to_str().unwrap())?.read() { 25 | let content = entry?; 26 | 27 | // Split content into words 28 | let words: Vec<&str> = content.split_whitespace().collect(); 29 | 30 | for word in words { 31 | if current_chunk.len() + word.len() + 1 > chunk_size { 32 | // If adding the next word would exceed chunk size, 33 | // save current chunk and start a new one 34 | if !current_chunk.is_empty() { 35 | chunks.push(current_chunk.trim().to_string()); 36 | current_chunk.clear(); 37 | } 38 | } 39 | current_chunk.push_str(word); 40 | current_chunk.push(' '); 41 | } 42 | } 43 | 44 | // last chunk 45 | if !current_chunk.is_empty() { 46 | chunks.push(current_chunk.trim().to_string()); 47 | } 48 | 49 | if chunks.is_empty() { 50 | anyhow::bail!("No content found in PDF file: {:?}", path); 51 | } 52 | 53 | Ok(chunks) 54 | } 55 | 56 | #[tokio::main] 57 | async fn main() -> Result<()> { 58 | // Initialize OpenAI client 59 | let openai_client = openai::Client::from_env(); 60 | 61 | // Load PDFs using Rig's built-in PDF loader 62 | let documents_dir = std::env::current_dir()?.join("documents"); 63 | 64 | let moores_law_chunks = load_pdf(documents_dir.join("Moores_Law_for_Everything.pdf")) 65 | .context("Failed to load Moores_Law_for_Everything.pdf")?; 66 | let last_question_chunks = load_pdf(documents_dir.join("The_Last_Question.pdf")) 67 | .context("Failed to load The_Last_Question.pdf")?; 68 | 69 | println!("Successfully loaded and chunked PDF documents"); 70 | 71 | // Create embedding model 72 | let model = openai_client.embedding_model(TEXT_EMBEDDING_ADA_002); 73 | 74 | // Create embeddings builder 75 | let mut builder = EmbeddingsBuilder::new(model.clone()); 76 | 77 | // Add chunks from Moore's Law 78 | for (i, chunk) in moores_law_chunks.into_iter().enumerate() { 79 | builder = builder.document(Document { 80 | id: format!("moores_law_{}", i), 81 | content: chunk, 82 | })?; 83 | } 84 | 85 | // Add chunks from The Last Question 86 | for (i, chunk) in last_question_chunks.into_iter().enumerate() { 87 | builder = builder.document(Document { 88 | id: format!("last_question_{}", i), 89 | content: chunk, 90 | })?; 91 | } 92 | 93 | // Build embeddings 94 | let embeddings = builder.build().await?; 95 | 96 | println!("Successfully generated embeddings"); 97 | 98 | // Create vector store and index 99 | let vector_store = InMemoryVectorStore::from_documents(embeddings); 100 | let index = vector_store.index(model); 101 | 102 | println!("Successfully created vector store and index"); 103 | 104 | // Create RAG agent 105 | let rag_agent = openai_client 106 | .agent("gpt-4") 107 | .preamble("You are a helpful assistant that answers questions based on the provided document context. When answering questions, try to synthesize information from multiple chunks if they're related.") 108 | .dynamic_context(4, index) // Increased to 4 since we have chunks now 109 | .build(); 110 | 111 | println!("Starting CLI chatbot..."); 112 | 113 | // Start interactive CLI 114 | rig::cli_chatbot::cli_chatbot(rag_agent).await?; 115 | 116 | Ok(()) 117 | } -------------------------------------------------------------------------------- /t250131-rig-text-classifier/Cargo.toml: -------------------------------------------------------------------------------- 1 | [package] 2 | name = "t250131-rig-text-classifier" 3 | version.workspace = true 4 | authors.workspace = true 5 | edition.workspace = true 6 | license.workspace = true 7 | readme.workspace = true 8 | description.workspace = true 9 | keywords.workspace = true 10 | categories.workspace = true 11 | homepage.workspace = true 12 | repository.workspace = true 13 | 14 | [dependencies] 15 | rig-core = "0.7.0" 16 | tokio = { version = "1.34.0", features = ["full"] } 17 | anyhow = "1.0.75" 18 | serde = { version = "1.0", features = ["derive"] } 19 | serde_json = "1.0" 20 | dotenv = "0.15.0" 21 | schemars = "0.8.21" 22 | -------------------------------------------------------------------------------- /t250131-rig-text-classifier/src/main.rs: -------------------------------------------------------------------------------- 1 | // Import necessary dependencies 2 | use rig::providers::openai; 3 | use schemars::JsonSchema; 4 | use serde::{Deserialize, Serialize}; 5 | 6 | // Define enum for sentiment classification 7 | #[derive(Debug, Deserialize, JsonSchema, Serialize)] 8 | enum Sentiment { 9 | Positive, 10 | Negative, 11 | Neutral, 12 | } 13 | 14 | // Define an enum for sentiment confidence level 15 | #[derive(Debug, Deserialize, JsonSchema, Serialize)] 16 | struct SentimentClassification { 17 | sentiment: Sentiment, 18 | confidence: f32, 19 | } 20 | 21 | // Define an enum to represent news article topics 22 | #[derive(Debug, Deserialize, JsonSchema, Serialize)] 23 | enum Topic { 24 | Politics, 25 | Technology, 26 | Sports, 27 | Entertainment, 28 | Other(String), 29 | } 30 | 31 | // Define a struct to hold the news article classification result 32 | #[derive(Debug, Deserialize, JsonSchema, Serialize)] 33 | struct NewsArticleClassification { 34 | topic: Topic, 35 | sentiment: SentimentClassification, 36 | summary: String, 37 | } 38 | 39 | fn pretty_print_result(article: &str, result: &NewsArticleClassification) { 40 | println!("Article: \"{}...\"", &article[..100]); // Print first 100 characters 41 | println!("Classification Result:"); 42 | println!(" Topic: {:?}", result.topic); 43 | println!(" Sentiment: {:?}", result.sentiment.sentiment); 44 | println!(" Confidence: {:.2}%", result.sentiment.confidence * 100.0); 45 | println!(" Summary: {}", result.summary); 46 | println!(); 47 | } 48 | 49 | #[tokio::main] 50 | async fn main() { 51 | // Initialize the OpenAI client 52 | let openai_client = openai::Client::from_env(); 53 | 54 | // Create a news article classifier using Rig's Extractor 55 | let news_classifier = openai_client 56 | .extractor::("gpt-4") 57 | .preamble(" 58 | You are a news article classification AI. For the given news article: 59 | 1. Classify the main topic (Politics, Technology, Sports, Entertainment, or Other). 60 | 2. Analyze the overall sentiment (Positive, Negative, or Neutral) with a confidence score. 61 | 3. Provide a brief summary of the article. 62 | ") 63 | .build(); 64 | 65 | // Sample news article to classify 66 | let article = " 67 | After conducting the first-ever commercial spacewalk and traveling farther from Earth than anyone \ 68 | in more than half a century, the astronauts of the Polaris Dawn mission returned to Earth safely \ 69 | early Sunday. 70 | 71 | The SpaceX Crew Dragon capsule splashed down in the Gulf of Mexico, off the coast of Dry Tortugas, \ 72 | Fla., shortly after 3:30 a.m., carrying Jared Isaacman, a billionaire entrepreneur, and his crew \ 73 | of three private astronauts, according to a SpaceX livestream. 74 | 75 | The ambitious space mission, a collaboration between Mr. Isaacman and Elon Musk's SpaceX, spent \ 76 | five days in orbit, achieved several milestones in private spaceflight and was further evidence \ 77 | that space travel and spacewalks are no longer the exclusive domain of professional astronauts \ 78 | working at government agencies like NASA. 79 | 80 | The Crew Dragon capsule launched on Tuesday, after delays because of a helium leak and bad weather. \ 81 | On board were Mr. Isaacman, the mission commander and the founder of the payment services company \ 82 | Shift4; Sarah Gillis and Anna Menon, SpaceX employees; and Scott Poteet, a retired U.S. Air Force \ 83 | lieutenant colonel. 84 | 85 | Late on Tuesday, its orbit reached a high point of about 870 miles above the Earth's surface. That \ 86 | beat the record distance for astronauts on a mission not headed to the moon, which the Gemini XI \ 87 | mission set in 1966 at 853 miles high, and made Ms. Gillis and Ms. Menon the first women ever to \ 88 | fly so far from Earth. 89 | 90 | On Thursday, Mr. Isaacman and Ms. Gillis became the first private astronauts to successfully complete \ 91 | a spacewalk. The operation involved the crew letting all the air out of the spacecraft, because it \ 92 | had no airlock, while the other two crew members wore spacesuits inside the airless capsule. Mr. \ 93 | Isaacman moved outside and conducted mobility tests of his spacesuit for a few minutes before \ 94 | re-entering the capsule. Ms Gillis then moved outside and performed the same tests. 95 | 96 | This was the first of three Polaris missions aimed at accelerating technological advances needed to \ 97 | fulfill Mr. Musk's dream of sending people to Mars someday. A key goal of the mission was to further \ 98 | the development of more advanced spacesuits that would be needed for SpaceX to try any future \ 99 | off-world colonization. 100 | 101 | During a news conference before the launch, Mr. Isaacman mused that one day, someone might step onto \ 102 | Mars wearing a version of the spacesuit that SpaceX had developed for this flight. Closer to Earth, \ 103 | commercial spacewalks also present other possibilities, like technicians repairing private satellites \ 104 | in orbit. 105 | 106 | During the spaceflight, the four astronauts conducted about 40 experiments, mostly about how \ 107 | weightlessness and radiation affect the human body. They also tested laser communications between \ 108 | the Crew Dragon and SpaceX's constellation of Starlink internet satellites.\ 109 | "; 110 | 111 | // Perform news article classification 112 | match news_classifier.extract(article).await { 113 | Ok(result) => pretty_print_result(article, &result), 114 | Err(e) => eprintln!("Error classifying article: {}", e), 115 | } 116 | } 117 | -------------------------------------------------------------------------------- /t250217-rig-ollama-deepseek-r1/Cargo.toml: -------------------------------------------------------------------------------- 1 | [package] 2 | name = "t250217-rig-ollama-deepseek-r1" 3 | version.workspace = true 4 | authors.workspace = true 5 | edition.workspace = true 6 | license.workspace = true 7 | readme.workspace = true 8 | description.workspace = true 9 | keywords.workspace = true 10 | categories.workspace = true 11 | homepage.workspace = true 12 | repository.workspace = true 13 | 14 | [dependencies] 15 | rig-core = { version = "0.8.0", features = ["pdf", "derive"] } 16 | tokio = { version = "1.34.0", features = ["full"] } 17 | anyhow = "1.0.75" 18 | serde = { version = "1.0", features = ["derive"] } 19 | serde_json = "1.0" 20 | dotenv = "0.15.0" 21 | schemars = "0.8.21" 22 | thiserror = "2.0.11" 23 | -------------------------------------------------------------------------------- /t250217-rig-ollama-deepseek-r1/src/main.rs: -------------------------------------------------------------------------------- 1 | use anyhow::{Context, Result}; 2 | use rig::{ 3 | embeddings::EmbeddingsBuilder, loaders::PdfFileLoader, providers::openai, 4 | vector_store::in_memory_store::InMemoryVectorStore, Embed, 5 | }; 6 | use serde::{Deserialize, Serialize}; 7 | use std::path::PathBuf; 8 | 9 | #[derive(Embed, Clone, Debug, Serialize, Deserialize, Eq, PartialEq)] 10 | struct Document { 11 | id: String, 12 | #[embed] 13 | content: String, 14 | } 15 | 16 | fn load_pdf(path: PathBuf) -> Result> { 17 | const CHUNK_SIZE: usize = 2000; 18 | 19 | let content_chunks = PdfFileLoader::with_glob(path.to_str().context("Invalid path")?)? 20 | .read() 21 | .into_iter() 22 | .filter_map(|result| { 23 | result 24 | .map_err(|e| { 25 | eprintln!("Error reading PDF content: {}", e); 26 | e 27 | }) 28 | .ok() 29 | }) 30 | .flat_map(|content| { 31 | let mut chunks = Vec::new(); 32 | let mut current = String::new(); 33 | 34 | for word in content.split_whitespace() { 35 | if current.len() + word.len() + 1 > CHUNK_SIZE && !current.is_empty() { 36 | chunks.push(std::mem::take(&mut current).trim().to_string()); 37 | } 38 | current.push_str(word); 39 | current.push(' '); 40 | } 41 | 42 | if !current.is_empty() { 43 | chunks.push(current.trim().to_string()); 44 | } 45 | 46 | chunks 47 | }) 48 | .collect::>(); 49 | 50 | if content_chunks.is_empty() { 51 | anyhow::bail!("No content found in PDF file: {}", path.display()); 52 | } 53 | 54 | Ok(content_chunks) 55 | } 56 | 57 | #[tokio::main] 58 | async fn main() -> Result<()> { 59 | // Initialize Ollama client 60 | let client = openai::Client::from_url("ollama", "http://localhost:11434/v1"); 61 | 62 | // Load PDFs using Rig's built-in PDF loader 63 | let documents_dir = std::env::current_dir()?.join("documents"); 64 | 65 | let pdf_chunks = 66 | load_pdf(documents_dir.join("Moores_Law_for_Everything.pdf")).context("Failed to load pdf documents")?; 67 | 68 | println!("Successfully loaded and chunked PDF documents"); 69 | 70 | // Create embedding model 71 | let model = client.embedding_model("bge-m3"); 72 | 73 | // Create embeddings builder 74 | let mut builder = EmbeddingsBuilder::new(model.clone()); 75 | 76 | // Add chunks from pdf documents 77 | for (i, chunk) in pdf_chunks.into_iter().enumerate() { 78 | builder = builder.document(Document { 79 | id: format!("pdf_document_{}", i), 80 | content: chunk, 81 | })?; 82 | } 83 | 84 | // Build embeddings 85 | let embeddings = builder.build().await?; 86 | 87 | println!("Successfully generated embeddings"); 88 | 89 | // Create vector store and index 90 | let vector_store = InMemoryVectorStore::from_documents(embeddings); 91 | let index = vector_store.index(model); 92 | 93 | println!("Successfully created vector store and index"); 94 | 95 | // Create RAG agent 96 | let rag_agent = client 97 | .agent("deepseek-r1") 98 | .preamble("You are a helpful assistant that answers questions based on the provided document context. When answering questions, try to synthesize information from multiple chunks if they're related.") 99 | .dynamic_context(1, index) 100 | .build(); 101 | 102 | println!("Starting CLI chatbot..."); 103 | 104 | // Start interactive CLI 105 | rig::cli_chatbot::cli_chatbot(rag_agent).await?; 106 | 107 | Ok(()) 108 | } 109 | -------------------------------------------------------------------------------- /video-qr.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/lispking/rust-tips/0c0968ef07b1aa5d7d9c2e84274133ef4642ad36/video-qr.png --------------------------------------------------------------------------------