質問編集履歴

7

GitHubのリポジトリを特定のコミットを指定

2022/12/21 11:56

投稿

akira_kano1101
akira_kano1101

スコア25

test CHANGED
File without changes
test CHANGED
@@ -57,10 +57,10 @@
57
57
  ### 本題
58
58
 
59
59
  創作したマクロのGitHubはこちらになります。
60
- [https://github.com/kano1101/perform-wasm](https://github.com/kano1101/perform-wasm)
60
+ [https://github.com/kano1101/perform-wasm/tree/3e4a68f0135baa8b5873826685ee810a314c993b](https://github.com/kano1101/perform-wasm/tree/3e4a68f0135baa8b5873826685ee810a314c993b)
61
61
 
62
62
  また、創作したマクロを使うコードもGitHubに保存しました。
63
- [https://github.com/kano1101/reexport](https://github.com/kano1101/reexport)
63
+ [https://github.com/kano1101/reexport/tree/1d1cb4651e92393a78235301f3c2acf3a436384f](https://github.com/kano1101/reexport/tree/1d1cb4651e92393a78235301f3c2acf3a436384f)
64
64
 
65
65
  今回は、これらのコードを使いたい場合に設定する「依存関係」についてが解決したい問題です。
66
66
 

6

文面を訂正

2022/12/19 08:09

投稿

akira_kano1101
akira_kano1101

スコア25

test CHANGED
File without changes
test CHANGED
@@ -54,7 +54,9 @@
54
54
 
55
55
  これを解決しようとしてみています。
56
56
 
57
+ ### 本題
58
+
57
- この創作したマクロのGitHubはこちらになります。
59
+ 創作したマクロのGitHubはこちらになります。
58
60
  [https://github.com/kano1101/perform-wasm](https://github.com/kano1101/perform-wasm)
59
61
 
60
62
  また、創作したマクロを使うコードもGitHubに保存しました。
@@ -73,7 +75,7 @@
73
75
 
74
76
  今の状況では、新たなプロジェクトでこのマクロを使用したい場合、上にリストした3つのクレートをそのプロジェクトでふたたび同じように`Cargo.toml`に追加する必要があります。これが問題です!
75
77
 
76
- `perform_wasm`を使うたびに毎回、同じ依存関係を記述しなければならないのが不便なのでこれをしなくてもコンパイルできるようにというのが今回実現したいことです。
78
+ `perform_wasm`を新たなプロジェクトが使うたびに毎回、同じ依存関係を記述しなければならないのが不便なのでこれをしなくてもコンパイルできるようにというのが今回実現したいことです。
77
79
 
78
80
  GitHubでも確認いただけますが参考までにマクロのコードを掲載します。
79
81
 

5

タイトル修正

2022/12/19 08:04

投稿

akira_kano1101
akira_kano1101

スコア25

test CHANGED
@@ -1 +1 @@
1
- [Rust]自作マクロ定義の中で外部クレートを使う場合、別のプロジェクトからそのマクロを使っても再度同じ外部クレートの依存関係をCargo.tomlにしなくて済むような方法がわからない
1
+ [Rust]自作マクロ定義の中で外部クレートを使う場合、別のプロジェクトからそのマクロを使っても再度同じ外部クレートの依存関係をCargo.tomlに記述しなくて済むような方法がわからない
test CHANGED
File without changes

4

タイトル修正

2022/12/19 08:03

投稿

akira_kano1101
akira_kano1101

スコア25

test CHANGED
@@ -1 +1 @@
1
- [Rust]自作マクロ定義の中で外部クレートを使ったら、別のプロジェクトからそのマクロを使いたい際に再度同じ外部クレートの依存関係をCargo.tomlに記述しなくて良い方法がないかわからない
1
+ [Rust]自作マクロ定義の中で外部クレートを使う場合、別のプロジェクトからそのマクロを使っても再度同じ外部クレートの依存関係をCargo.tomlにしなくて済むような方法がわからない
test CHANGED
File without changes

3

文面をわかりやすいよう修正

2022/12/19 07:59

投稿

akira_kano1101
akira_kano1101

スコア25

test CHANGED
File without changes
test CHANGED
@@ -1,18 +1,66 @@
1
1
  ### 前提
2
2
 
3
+ Rustでの質問で、前提の話になります。
4
+
3
- Rustで`wasm_bindgen_futures`クレートの関数`spawn_local`を使う際、与える引数`Future`の問題を解消して使いやすくするマクロを作っています。
5
+ ブラウザ上動作する`wasm`に、`wasm_bindgen_futures`クレートの関数`spawn_local`を使っています。
6
+
7
+ 非同期処理(`async`、`await`)を要求するメソッドを`async`ブロックに仕込んでこの関数に引数で与えたいとした場合に起きた話です。
8
+
9
+ ライフタイムの短い参照は`async`ブロック内に入れられません。
10
+
11
+ 例えば`egui`クレートの頻出のパラメータ`ui: &mut Ui`を`async`ブロック内部に入れようと思って`ui.label()`などを使って`reqwest::get()`の結果の値を非同期にスクリーンに表示したいと考えた場合など、そういうときにライフタイムの問題が言われ、コンパイルできません。
12
+
13
+ `wasm`で典型的なパターンの問題と思われます。
14
+
15
+ ```rust
16
+ fn update(&mut self, ctx: &egui::Context, _frame: &mut eframe::Frame) {
17
+ egui::TopBottomPanel::top("select_tab").show(ctx, |ui| {
18
+ wasm_bindgen_futures::spawn_local(async {
19
+ let ip = reqwest::get("http://httpbin.org/ip")
20
+ .await
21
+ .unwrap()
22
+ .text()
23
+ .await
24
+ .unwrap();
25
+ // ui.label(ip); // 'staticなFuture内部にライフタイムの短い参照uiを入れられない
26
+ });
27
+ });
28
+ }
29
+ ```
30
+
31
+ 解決策として次のように考えました。
32
+
33
+ ```rust
34
+ build_perform!(ip, i32, String);
35
+
36
+ fn display(&self, ui: &mut Ui) -> Option<()> {
37
+ let f = async {
38
+ reqwest::get("http://httpbin.org/ip")
39
+ .await
40
+ .unwrap()
41
+ .text()
42
+ .await
43
+ .unwrap()
44
+ };
45
+ ip::perform::set_begin(1, f);
46
+ let ip = ip::perform::try_fetch(1)?;
47
+ ui.label(ip);
48
+ Some(())
49
+ }
50
+ ```
51
+ `Future`トレイト内で非同期処理を行なった結果の値を外に出そうと考えました。
4
52
 
5
53
  この関数は普通に使うには、与えられる引数のトレイト境界条件が`Future<Output = ()> + 'static`であることにより戻り値が`()`であることもあって、簡単に`async`ブロックから外に値を取り出せないところあるためが使いづらいです。
6
54
 
7
55
  これを解決しようとしてみています。
8
56
 
9
- 創作したマクロのGitHubはこちらになります。
57
+ この創作したマクロのGitHubはこちらになります。
10
58
  [https://github.com/kano1101/perform-wasm](https://github.com/kano1101/perform-wasm)
11
59
 
12
60
  また、創作したマクロを使うコードもGitHubに保存しました。
13
61
  [https://github.com/kano1101/reexport](https://github.com/kano1101/reexport)
14
62
 
15
- 今回は、これらのコードを使う際発生する依存関係に関することが解決したい問題です。
63
+ 今回は、これらのコードを使いたい場合設定する依存関係ついてが解決したい問題です。
16
64
 
17
65
  ### 実現したいこと
18
66
 
@@ -23,7 +71,7 @@
23
71
  - `tokio`
24
72
  - `wasm_bindgen_futures`
25
73
 
26
- 今の状況では、新たなプロジェクトでこのマクロを使用したい場合、上にリストした3つのクレートをそのプロジェクトでふたたび同じように`Cargo.toml`に追加する必要があります。
74
+ 今の状況では、新たなプロジェクトでこのマクロを使用したい場合、上にリストした3つのクレートをそのプロジェクトでふたたび同じように`Cargo.toml`に追加する必要があります。これが問題です!
27
75
 
28
76
  `perform_wasm`を使うたびに毎回、同じ依存関係を記述しなければならないのが不便なのでこれをしなくてもコンパイルできるようにというのが今回実現したいことです。
29
77
 
@@ -122,8 +170,6 @@
122
170
 
123
171
  `perform_wasm`を利用する側の別の新たなプロジェクトにも`Cargo.toml`の依存関係に前述でリストした3つの依存クレートを含めなければコンパイルが通りません。
124
172
 
125
- 逆に、含めればコンパイルは通ります。
126
-
127
173
  ```console
128
174
  error[E0433]: failed to resolve: use of undeclared crate or module `once_cell`
129
175
  --> src/main.rs:11:5
@@ -154,6 +200,8 @@
154
200
  error: could not compile `reexport` due to 3 previous errors
155
201
  Serving HTTP on :: port 8080 (http://[::]:8080/) ...
156
202
  ```
203
+
204
+ 逆に、含めればコンパイルは通ります。
157
205
 
158
206
  ### 該当のソースコード
159
207
 

2

ファイル名の追記

2022/12/19 07:15

投稿

akira_kano1101
akira_kano1101

スコア25

test CHANGED
File without changes
test CHANGED
@@ -29,6 +29,7 @@
29
29
 
30
30
  GitHubでも確認いただけますが参考までにマクロのコードを掲載します。
31
31
 
32
+ ##### perform_wasm/src/lib.rs
32
33
  ```rust
33
34
  #[macro_export]
34
35
  macro_rules! build_perform {
@@ -156,6 +157,7 @@
156
157
 
157
158
  ### 該当のソースコード
158
159
 
160
+ ##### reexport/Cargo.toml
159
161
  ```toml
160
162
  [package]
161
163
  name = "reexport"
@@ -177,6 +179,7 @@
177
179
  # wasm-bindgen-futures = "0.4.33"
178
180
  ```
179
181
 
182
+ ##### reexport/src/main.rs
180
183
  ```rust
181
184
  fn main() {
182
185
  console_error_panic_hook::set_once();
@@ -194,7 +197,7 @@
194
197
 
195
198
  ### 試したこと
196
199
 
197
- ##### run.sh
200
+ ##### reexport/run.sh
198
201
  ```bash
199
202
  (
200
203
  cd `dirname $0`
@@ -206,6 +209,8 @@
206
209
 
207
210
  ##### 実行したコマンド
208
211
  ```console
212
+ % pwd
213
+ /Users/a.kano/development/temp/reexport
209
214
  % ./run.sh
210
215
  ```
211
216
 

1

reexportのGitHubを追加と文面がわかりにくいところを修正

2022/12/19 07:11

投稿

akira_kano1101
akira_kano1101

スコア25

test CHANGED
@@ -1 +1 @@
1
- [Rust]自作マクロ定義の中で外部クレートを使ったら、別のプロジェクトからそのマクロを使いたい際に再度同じ外部クレートの依存関係をCargo.tomlに記述する必要あるの
1
+ [Rust]自作マクロ定義の中で外部クレートを使ったら、別のプロジェクトからそのマクロを使いたい際に再度同じ外部クレートの依存関係をCargo.tomlに記述しなくて良い方法ないわからない
test CHANGED
@@ -1,29 +1,127 @@
1
1
  ### 前提
2
2
 
3
- Rustで`wasm_bindgen_futures`クレートを使う際`'static`の問題を解使いやすくするマクロを作っています。
3
+ Rustで`wasm_bindgen_futures`クレートの関数`spawn_local`を使う際、与える引数`Future`の問題を解使いやすくするマクロを作っています。
4
-
4
+
5
- このクレートは普通に使うには`Future<Output = ()> + 'static`により戻り値が`()`であ、簡単に`async`ブロックから外に値を取り出せないところが使いづらいためです。
5
+ この関数は普通に使うには、与えられる引数のトレイト境界条件が`Future<Output = ()> + 'static`であることにより戻り値が`()`であることもあって、簡単に`async`ブロックから外に値を取り出せないところあるためが使いづらいです。
6
+
6
-
7
+ これを解決しようとしてみています。
8
+
7
- GitHubはこちらになります。
9
+ 創作したマクロのGitHubはこちらになります。
8
10
  [https://github.com/kano1101/perform-wasm](https://github.com/kano1101/perform-wasm)
9
11
 
12
+ また、創作したマクロを使うコードもGitHubに保存しました。
13
+ [https://github.com/kano1101/reexport](https://github.com/kano1101/reexport)
14
+
10
- これを使う際に発生する依存関係に関することが問題です。
15
+ 今回は、これらのコードを使う際に発生する依存関係に関することが解決したい問題です。
11
16
 
12
17
  ### 実現したいこと
13
18
 
19
+ 創作したマクロのプロジェクトは`perform_wasm`と名付けました。
20
+
14
- のマクロの中では、クレート`once_cell`、`tokio`、`wasm_bindgen_futures`のモジュールをuseしています。
21
+ `perform_wasm`中のマクロでは、以下のクレートのモジュールをuseしています。
15
-
22
+ - `once_cell`
23
+ - `tokio`
24
+ - `wasm_bindgen_futures`
25
+
16
- 私の今の状況では、新たなのプロジェクトでこのマクロを使用したい場合、`once_cell`、`tokio`、`wasm_bindgen_futures`をふたたび同じように`Cargo.toml`に追加する必要があります。
26
+ 今の状況では、新たなのプロジェクトでこのマクロを使用したい場合、上にリストした3つのクレートそのプロジェクトでふたたび同じように`Cargo.toml`に追加する必要があります。
17
-
27
+
18
- 作ったクレートを使うた再度同じ依存関係を記述しなければならないのが不便なのでこれをしなくてもコンパイルできるようにというのが今回実現したいことです。
28
+ `perform_wasm`を使うた毎回、同じ依存関係を記述しなければならないのが不便なのでこれをしなくてもコンパイルできるようにというのが今回実現したいことです。
29
+
19
-
30
+ GitHubでも確認いただけますが参考までにマクロのコードを掲載します。
31
+
32
+ ```rust
33
+ #[macro_export]
34
+ macro_rules! build_perform {
35
+ ($space:ident, $key:ty, $value:ty) => {
36
+ mod $space {
37
+ pub mod perform {
38
+ use once_cell::sync::OnceCell;
39
+ use std::collections::HashMap;
40
+ use std::future::Future;
41
+ use std::hash::Hash;
42
+ use tokio::sync::Mutex;
43
+ use wasm_bindgen_futures::spawn_local;
44
+ static STORE: OnceCell<Mutex<HashMap<$key, $value>>> = OnceCell::new();
45
+
46
+ fn global_data() -> &'static Mutex<HashMap<$key, $value>>
47
+ where
48
+ $key: Hash,
49
+ $value: Default,
50
+ {
51
+ STORE.get_or_init(|| {
52
+ let hash_map = HashMap::new();
53
+ Mutex::new(hash_map)
54
+ })
55
+ }
56
+
57
+ async fn lock_and_do_mut<F>(f: F) -> Option<$value>
58
+ where
59
+ F: FnOnce(&mut HashMap<$key, $value>) -> Option<$value>,
60
+ $key: Hash,
61
+ {
62
+ let mut hash_map = global_data().lock().await;
63
+ f(&mut *hash_map)
64
+ }
65
+
66
+ async fn lock_and_do<F>(f: F) -> Option<$value>
67
+ where
68
+ F: Fn(&HashMap<$key, $value>) -> Option<$value>,
69
+ {
70
+ let hash_map = global_data().lock().await;
71
+ f(&*hash_map)
72
+ }
73
+ #[allow(dead_code)]
74
+ fn try_lock_and_do<F>(f: F) -> Option<$value>
75
+ where
76
+ F: Fn(&HashMap<$key, $value>) -> Option<$value>,
77
+ {
78
+ let hash_map = global_data().try_lock().ok()?;
79
+ f(&*hash_map)
80
+ }
81
+
82
+ fn get_and_clone(key: $key, hash_map: &HashMap<$key, $value>) -> Option<$value>
83
+ where
84
+ $value: Clone,
85
+ {
86
+ hash_map.get(&key).map(|v| v.clone())
87
+ }
88
+
89
+ pub async fn set_async<Fut>(key: $key, f: Fut)
90
+ where
91
+ Fut: Future<Output = $value> + 'static,
92
+ {
93
+ let value = f.await;
94
+ lock_and_do_mut(|hash_map| hash_map.insert(key, value)).await;
95
+ }
96
+ #[allow(dead_code)]
97
+ = pub fn set_begin<Fut>(key: $key, f: Fut)
98
+ where
99
+ Fut: Future<Output = $value> + 'static,
100
+ {
101
+ spawn_local(async move {
102
+ let value = f.await;
103
+ lock_and_do_mut(|hash_map| hash_map.insert(key, value)).await;
104
+ });
105
+ }
20
- マクロを実装したプロジェクト側(`perform_wasm`)に修正を入れなければならないのか、どこをどうすると良いのかまでわかっていません。
106
+ pub async fn fetch_async(key: $key) -> Option<$value> {
107
+ lock_and_do(|hash_map| get_and_clone(key, hash_map)).await
108
+ }
109
+ #[allow(dead_code)]
110
+ pub fn try_fetch(key: $key) -> Option<$value> {
111
+ let value = try_lock_and_do(|hash_map| get_and_clone(key, hash_map))?;
112
+ Some(value)
113
+ }
114
+ }
115
+ }
116
+ };
117
+ }
118
+ ```
21
119
 
22
120
  ### 発生している問題・エラーメッセージ
23
121
 
24
- 再度記載しますが、GitHubのソースコードも提示させていただいた自作のクレート`perform_wasm`の中では`once_cell`、`tokio`、`wasm_bindgen_futures`を使っています。
25
-
26
- そして、`perform_wasm`を利用する側の別の新たなプロジェクトにも`Cargo.toml`の依存関係`[dependencies]`これら依存クレートを含めなければコンパイルが通りません。
122
+ `perform_wasm`を利用する側の別の新たなプロジェクトにも`Cargo.toml`の依存関係に前述でリストした3つの依存クレートを含めなければコンパイルが通りません。
123
+
124
+ 逆に、含めればコンパイルは通ります。
27
125
 
28
126
  ```console
29
127
  error[E0433]: failed to resolve: use of undeclared crate or module `once_cell`
@@ -125,7 +223,10 @@
125
223
  cargo 1.65.0 (4bc8f24d3 2022-10-20)
126
224
  ```
127
225
 
128
- プロジェクトを作るたびにそれら全てのクレートを依存関係に含めなければならないとなると、せっかく良い機能をクレートとしてブラックボックス化しているのに意味がないと思います。
226
+ 論点を戻すと、毎回依存クレートをdependenciesに記述すれば動作はしますので、それで解決ということにもしても良いところかもしれませんが、プロジェクトを作るたびに余分なクレートを依存関係に含めなければならないとなると、せっかく良い機能をクレートとしてブラックボックス化しているのに意味がないと思います。
227
+
228
+ `perform_wasm`に修正を入れなければならないのか、`reexport`の修正で済むのか、どう修正すると解決できるのかがわかりません。
229
+
129
230
 
130
231
  この現象の解決方法をご存知の方、もしいらっしゃいましたらご教示願えますと幸いです。
131
232