Skip to content

Commit 22e311f

Browse files
committed
refactor(leetcode): use async
1 parent e9b1154 commit 22e311f

File tree

9 files changed

+638
-442
lines changed

9 files changed

+638
-442
lines changed

Cargo.lock

+559-376
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

Cargo.toml

+6-1
Original file line numberDiff line numberDiff line change
@@ -10,16 +10,21 @@ members = ["./sort"]
1010

1111
[dependencies]
1212
git2 = "0.14.4"
13-
reqwest = { version = "0.11.11", features = ["blocking", "json"] }
13+
reqwest = { version = "0.11.11", features = ["json"] }
1414
serde_json = "1.0"
1515
serde = { version = "1.0", features = ["derive"] }
1616
clap = "3.0.0-beta.2"
1717
tera = "1.12.1"
1818
lazy_static = "1.4.0"
1919
regex = "1"
2020
rand = "0.8.4"
21+
tokio = { version = "1.33.0", features = ["fs", "macros", "rt-multi-thread"] }
22+
tokio-stream = { version = "0.1.14", features = ["fs"] }
2123

2224

2325
[[bin]]
2426
name = "leetcode"
2527
path = "src/main.rs"
28+
29+
[dev-dependencies]
30+
tokio = { version = "1.33.0", features = ["macros", "rt"] }

src/all.rs

+8-9
Original file line numberDiff line numberDiff line change
@@ -1,12 +1,11 @@
1-
use crate::file;
1+
use std::sync::{Arc, Mutex};
22

3+
use crate::file;
34
use crate::http::Resp;
4-
use std::sync::{Arc, Mutex};
5-
use std::thread;
65

76
/// 重新格式化
8-
pub fn all() {
9-
let files = file::get_all_bin_file();
7+
pub async fn all() {
8+
let files = file::get_all_bin_file().await;
109

1110
let v = Vec::<Resp>::with_capacity(files.len());
1211

@@ -23,18 +22,18 @@ pub fn all() {
2322

2423
let x = x.clone();
2524

26-
handlers.push(thread::spawn(move || {
25+
handlers.push(tokio::spawn(async move {
2726
for i in files {
2827
println!("{} downloading", i);
29-
let resp = crate::http::get_question_info(&i);
28+
let resp = crate::http::get_question_info(&i).await;
3029
x.lock().unwrap().push(resp);
3130
}
3231
}))
3332
}
3433

3534
for i in handlers {
36-
i.join().unwrap();
35+
i.await.unwrap();
3736
}
3837

39-
crate::file::write_readme(&mut *x.lock().unwrap());
38+
file::write_readme(&mut *x.lock().unwrap()).await;
4039
}

src/file.rs

+29-23
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,9 @@
11
use lazy_static::lazy_static;
22
use regex::Regex;
3-
use std::fs::{self, File};
4-
use std::io::Write;
3+
use tokio::fs::{self, File};
4+
use tokio::io::AsyncWriteExt;
5+
use tokio_stream::wrappers::ReadDirStream;
6+
use tokio_stream::StreamExt;
57

68
use crate::http::{Data, Difficulty, Ques, Resp};
79

@@ -12,7 +14,7 @@ lazy_static! {
1214
}
1315

1416
/// 将结果写入README.md中
15-
pub fn write_readme(r: &mut Vec<Resp>) {
17+
pub async fn write_readme(r: &mut Vec<Resp>) {
1618
// 先按id排序
1719
r.sort_by(|x, y| {
1820
let x_id = x.data.question.question_id.parse::<i32>().unwrap();
@@ -21,36 +23,39 @@ pub fn write_readme(r: &mut Vec<Resp>) {
2123
});
2224
let s = crate::render::render(r).unwrap();
2325

24-
match std::fs::write("README.md", s) {
26+
match tokio::fs::write("README.md", s).await {
2527
Ok(_) => (),
2628
Err(e) => eprintln!("写入 README.md 失败,err{}", e.to_string()),
2729
}
2830
}
2931

3032
/// 获取 src/bin 目录下所有文件的名称
31-
pub fn get_all_bin_file() -> Vec<String> {
32-
let dir = fs::read_dir("src/bin/").unwrap();
33-
dir.into_iter()
34-
.map(|x| {
33+
pub async fn get_all_bin_file() -> Vec<String> {
34+
let mut dir = ReadDirStream::new(fs::read_dir("src/bin/").await.unwrap());
35+
let mut v = vec![];
36+
while let Some(x) = dir.next().await {
37+
v.push(
3538
x.unwrap()
3639
.file_name()
3740
.to_str()
3841
.unwrap()
3942
.trim_end_matches(".rs")
40-
.to_string()
41-
})
42-
.collect()
43+
.to_string(),
44+
);
45+
}
46+
47+
v
4348
}
4449

4550
/// 创建 bin/{quest_name}.rs 文件
46-
pub fn write_question(resp: Resp) {
51+
pub async fn write_question(resp: Resp) {
4752
let file = format!("src/bin/{}.rs", resp.data.question.title_slug);
4853
if std::path::Path::new(file.as_str()).exists() {
4954
eprintln!("{} exists", file);
5055
return;
5156
}
5257

53-
let mut f = File::create(file.as_str()).unwrap();
58+
let mut f = File::create(file.as_str()).await.unwrap();
5459
let mut s = String::new();
5560
s.push_str("#![allow(dead_code, unused, unused_variables, non_snake_case)]\n\n");
5661
s.push_str("fn main() {}\n\n");
@@ -64,12 +69,12 @@ pub fn write_question(resp: Resp) {
6469
}
6570
}
6671

67-
f.write_all(s.as_bytes()).unwrap();
72+
f.write_all(s.as_bytes()).await.unwrap();
6873
}
6974

7075
/// 解析README.md
71-
pub fn parse_readme() -> Vec<Resp> {
72-
let contents = fs::read_to_string("README.md").unwrap();
76+
pub async fn parse_readme() -> Vec<Resp> {
77+
let contents = fs::read_to_string("README.md").await.unwrap();
7378
parse(&contents)
7479
}
7580

@@ -96,11 +101,12 @@ fn parse(contents: &str) -> Vec<Resp> {
96101

97102
#[cfg(test)]
98103
mod tests {
99-
use crate::file::{get_all_bin_file, parse};
104+
use super::get_all_bin_file;
105+
use super::parse;
100106

101-
#[test]
102-
fn test_parse_readme() {
103-
let contents = std::fs::read_to_string("README.md").unwrap();
107+
#[tokio::test]
108+
async fn test_parse_readme() {
109+
let contents = tokio::fs::read_to_string("README.md").await.unwrap();
104110
let x = parse(&contents);
105111
println!("{:?}", x);
106112
println!("{}", x.len());
@@ -116,8 +122,8 @@ mod tests {
116122
}
117123
}
118124

119-
#[test]
120-
fn test_get_all_bin_file() {
121-
println!("{:?}", get_all_bin_file());
125+
#[tokio::test]
126+
async fn test_get_all_bin_file() {
127+
println!("{:?}", get_all_bin_file().await);
122128
}
123129
}

src/git.rs

+6-6
Original file line numberDiff line numberDiff line change
@@ -1,20 +1,20 @@
1-
use git2::{Repository, StatusOptions};
2-
31
use std::process::Command;
42

3+
use git2::{Repository, StatusOptions};
4+
55
/// 把新文件加入到git中
6-
pub fn push() {
6+
pub async fn push() {
77
// 解析readme.md文件
8-
let mut r = crate::file::parse_readme();
8+
let mut r = crate::file::parse_readme().await;
99
let new_file = get_uncommit_files();
1010
for i in new_file.iter() {
1111
let x = i.trim_end_matches(".rs"); // 去掉后缀
1212
let x = x.trim_start_matches("src/bin/"); // 去掉路径
1313
git_add(i);
14-
r.push(crate::http::get_question_info(x));
14+
r.push(crate::http::get_question_info(x).await);
1515
}
1616

17-
crate::file::write_readme(&mut r);
17+
crate::file::write_readme(&mut r).await;
1818
git_add("README.md");
1919
push_to_origin();
2020
}

src/http.rs

+16-14
Original file line numberDiff line numberDiff line change
@@ -2,9 +2,9 @@ use std::fmt;
22

33
use lazy_static::lazy_static;
44
use regex::Regex;
5-
use reqwest::blocking::Client;
6-
use serde::{Deserialize, Deserializer, Serialize, Serializer};
5+
use reqwest::Client;
76
use serde::de::{Error, Visitor};
7+
use serde::{Deserialize, Deserializer, Serialize, Serializer};
88

99
lazy_static! {
1010
static ref RE: Regex = Regex::new(r".*?/problems/(.*?)/").unwrap();
@@ -32,8 +32,8 @@ impl Difficulty {
3232

3333
impl Serialize for Difficulty {
3434
fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
35-
where
36-
S: Serializer,
35+
where
36+
S: Serializer,
3737
{
3838
match self {
3939
Self::Easy => serializer.serialize_str("Easy"),
@@ -45,8 +45,8 @@ impl Serialize for Difficulty {
4545

4646
impl<'de> Deserialize<'de> for Difficulty {
4747
fn deserialize<D>(deserializer: D) -> Result<Self, D::Error>
48-
where
49-
D: Deserializer<'de>,
48+
where
49+
D: Deserializer<'de>,
5050
{
5151
struct DifficultyVisitor;
5252

@@ -58,8 +58,8 @@ impl<'de> Deserialize<'de> for Difficulty {
5858
}
5959

6060
fn visit_str<E>(self, v: &str) -> Result<Self::Value, E>
61-
where
62-
E: Error,
61+
where
62+
E: Error,
6363
{
6464
match v {
6565
"Easy" => Ok(Self::Value::Easy),
@@ -110,7 +110,7 @@ pub struct Resp {
110110
pub data: Data,
111111
}
112112

113-
pub fn get_question_info(mut ques: &str) -> Resp {
113+
pub async fn get_question_info(mut ques: &str) -> Resp {
114114
if ques.starts_with("http") {
115115
ques = RE
116116
.captures_iter(ques)
@@ -131,21 +131,23 @@ pub fn get_question_info(mut ques: &str) -> Resp {
131131
.header("content-type", "application/json")
132132
.body(data)
133133
.send()
134+
.await
134135
.unwrap()
135136
.json::<Resp>()
137+
.await
136138
.expect(format!("{} download failed", ques).as_str())
137139
}
138140

139141
#[cfg(test)]
140142
mod tests {
141-
use crate::http::get_question_info;
143+
use super::get_question_info;
142144

143-
#[test]
144-
fn test_get_question_info() {
145-
println!("{:?}", get_question_info("container-with-most-water"));
145+
#[tokio::test]
146+
async fn test_get_question_info() {
147+
println!("{:?}", get_question_info("container-with-most-water").await);
146148
println!(
147149
"{:?}",
148-
get_question_info("https://leetcode-cn.com/problems/container-with-most-water/")
150+
get_question_info("https://leetcode-cn.com/problems/container-with-most-water/").await
149151
);
150152
}
151153
}

src/lib.rs

+8-8
Original file line numberDiff line numberDiff line change
@@ -1,15 +1,15 @@
1+
use std::process;
2+
3+
use clap::{App, Arg};
4+
15
mod all;
26
mod file;
37
mod git;
48
mod http;
59
mod new;
610
mod render;
711

8-
use clap::{App, Arg};
9-
10-
use std::process;
11-
12-
pub fn run() {
12+
pub async fn run() {
1313
let matches = App::new("leetcode")
1414
.version("0.0.1")
1515
.author("bestgopher <84328409@qq.com>")
@@ -26,15 +26,15 @@ pub fn run() {
2626

2727
if let Some(matches) = matches.subcommand_matches("new") {
2828
match matches.value_of_t::<String>("question_name") {
29-
Ok(x) => new::new(x),
29+
Ok(x) => new::new(x).await,
3030
Err(_) => {
3131
eprintln!("please input the name of question");
3232
process::exit(1);
3333
}
3434
}
3535
} else if matches.subcommand_matches("all").is_some() {
36-
all::all();
36+
all::all().await;
3737
} else {
38-
git::push();
38+
git::push().await;
3939
}
4040
}

src/main.rs

+3-2
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,4 @@
1-
fn main() {
2-
leetcode::run();
1+
#[tokio::main]
2+
async fn main() {
3+
leetcode::run().await;
34
}

src/new.rs

+3-3
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,7 @@
22
/// 2.如果name是url,就不需要拼装,不是就需要拼装
33
/// 3.请求结构,获取数据
44
/// 4.将数据写入bin/{question_name}.rs文件中
5-
pub fn new(ques: String) {
6-
let r = crate::http::get_question_info(ques.as_str());
7-
crate::file::write_question(r);
5+
pub async fn new(ques: String) {
6+
let r = crate::http::get_question_info(ques.as_str()).await;
7+
crate::file::write_question(r).await;
88
}

0 commit comments

Comments
 (0)