1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
/// Asynchronous utilities for working with Tokio runtime and async operations
///
/// Provides functionality for:
/// - Blocking on async operations
/// - Running system commands asynchronously
///
/// # Examples
///
/// ```ignore
/// #[allow(warnings)]
/// fn main() {
/// // Block on an async operation
/// asyncrs::block_on(async {
/// let output = asyncrs::command("echo hello").await;
/// println!("{}", String::from_utf8_lossy(&output.stdout));
/// });
/// let rt = doe::asyncrs::runtime::Builder::new_multi_thread()
/// .enable_all()
/// .build()
/// .unwrap();
/// rt.block_on(run());
/// rt.block_on(async {
/// run().await;
/// });
/// }
///
/// async fn run() {}
///
/// ```
#[allow(warnings)]
#[cfg(feature = "asyncrs")]
pub mod asyncrs {
pub use tokio;
pub use tokio::runtime::Runtime;
pub use tokio::*;
use crate::Vector;
/// Trait for blocking on async operations
///
/// Provides a method to block the current thread until a future completes
use std::future::Future;
pub trait BlockOn: Future + Send + 'static {
/// Runs the future to completion on a new multi‑threaded Tokio runtime,
/// blocking the current thread until it finishes.
///
/// # Panics
///
/// ```ignore
/// use doe::asyncrs::BlockOn;
///
/// fn main() {
/// run().block_on();
/// }
///
/// async fn run() {
/// println!("start");
/// use doe::httprs::*;
/// let headers = r#"
/// POST /api/v3/translate HTTP/1.1
/// Host: demo.com
/// Connection: keep-alive
/// Content-Length: 271
/// Accept-Language: zh-CN,zh;q=0.9
/// "#.to_headers();
/// let client = doe::httprs::async_client().await;
/// let resp = client.post("https://demo.com/api/v3/translate")
/// .headers(headers)
/// .body(doe::json::json!({"content":"由于","unionid":"ozM5_0WbKEDN6WmhHAphhBoVCUGE","openid":"o7jUU0dPlvcvDQwnfAcTPEuMxrD8","source_flag":"wxd511b28a58c8d268","source":"汉维翻译小程序大号"}).to_string())
/// .send().await.unwrap().text().await.unwrap();
/// std::fs::write("resp.json", resp).unwrap();
/// }
/// ```
///
/// Panics if a new Tokio runtime cannot be created.
fn block_on(self) -> Self::Output
where
Self: Sized,
{
let rt = tokio::runtime::Builder::new_multi_thread()
.enable_all()
.build()
.unwrap();
rt.block_on(self)
}
}
// Blanket implementation: every future that is Send + 'static
// automatically gets the .block_on() method.
impl<F, T> BlockOn for F where F: Future<Output = T> + Send + 'static {}
/// Blocks the current thread on the given future, executing it to completion
///
/// Creates a new Tokio runtime and uses it to run the provided future
///
/// # Arguments
///
/// * `future` - A future that will be blocked on
///
/// # Panics
///
/// Panics if unable to create a new Tokio runtime
pub fn block_on<F, T>(future: F) -> T
where
F: std::future::Future<Output = T> + Send + 'static,
{
let rt = tokio::runtime::Builder::new_multi_thread()
.enable_all()
.build()
.unwrap();
rt.block_on(future)
}
/// Executes a system command asynchronously
///
/// # Arguments
///
/// * `command` - The command to execute, can be a string or byte slice
///
/// # Returns
///
/// Returns a `std::process::Output` containing the command's output
///
/// # Panics
///
/// Panics if unable to spawn the child process
///
/// # Example
///
/// ```
/// use doe::asyncrs;
///
/// asyncrs::block_on(async {
/// let output = asyncrs::command("echo hello").await;
/// println!("{}", String::from_utf8_lossy(&output.stdout));
/// });
/// ```
pub async fn command(command: impl AsRef<[u8]>) -> std::process::Output {
use std::process::Stdio;
use tokio::process::Command;
let command = command.as_ref().to_string_lossy().to_string();
let exe = command.split(" ").into_iter().nth(0).unwrap();
let other = command.split(" ").into_iter().skip(1).collect::<Vec<_>>();
let child = Command::new(exe)
.args(other)
.stdin(Stdio::piped())
.stdout(Stdio::piped())
.stderr(Stdio::piped())
.spawn()
.expect("Failed to spawn child process");
let output = child
.wait_with_output()
.await
.expect("Failed to wait on child");
output
}
}
#[cfg(feature = "asyncrs")]
pub use asyncrs::*;