Comprehensive Rust ãžãããã ðŠ
ããã¯ãGoogle ã® Android ããŒã ãéçºããç¡æã® Rust ã³ãŒã¹ã§ãããã®ã³ãŒã¹ ã§ã¯ãåºæ¬çãªæ§æããããžã§ããªã¯ã¹ããšã©ãŒãã³ããªã³ã°ã®ãããªé«åºŠãªããã㯠ãŸã§ãRust ã®å šç¯å²ãæ±ããŸãã
ã³ãŒã¹ã®ææ°ããŒãžã§ã³ã¯ https://google.github.io/comprehensive-rust/ ã§ç¢ºèªã§ããŸãããããå¥ã®å Žæã§ èªãã§ããå Žåã¯ãæŽæ°ã«ã€ããŠãã¡ãã確èªããŠãã ããã
ãã®ã³ãŒã¹ã¯ä»ã®èšèªã§ãå©çšã§ããŸããããŒãžå³äžã§åžæã®èšèªãéžæãããã å©çšå¯èœãªãã¹ãŠã®ç¿»èš³ã®äžèЧã«ã€ããŠã¯ 翻蚳 ããŒãžã確èªããŠãã ããã
ãã®ã³ãŒã¹ã¯ PDF ç ã§ãå©çšã§ããŸãã
ãã®ã³ãŒã¹ã®ç®çã¯ãRust ãåŠãã§ãããããšã§ããåè¬è 㯠Rust ã«ã€ããŠäœãç¥ã ãªãããšãåæãšããæ¬¡ãç®æããŸã:
- Rust ã®æ§æãšèšèªã«ã€ããŠå æ¬çã«çè§£ããŠãããã
- æ¢åã®ããã°ã©ã ãä¿®æ£ããRust ã§æ°ããããã°ã©ã ãæžããããã«ãªã£ãŠãããã
- Rust ã®äžè¬çãªã€ãã£ãªã ã玹ä»ããã
æåã® 4 æ¥éã®ã³ãŒã¹ã Rust Fundamentals ãšåŒã³ãŸãã
ãã®åºç€ã®äžã«ã1 ã€ä»¥äžã®å°éãããã¯ãããã«æ·±ãåŠã¶ããšãã§ããŸã:
- Android: Android ãã©ãããã©ãŒã éçº (AOSP) ã§ Rust ã䜿ã忥 ã³ãŒã¹ã§ããããã«ã¯ãCãC++ãJava ãšã®çžäºéçšãå«ãŸããŸãã
- Chromium: Chromium ããŒã¹ã®ãã©ãŠã¶ãŒã§ Rust ã䜿ã忥ã³ãŒã¹ ã§ããããã«ã¯ãC++ ãšã®çžäºéçšããChromium ã«ãµãŒãããŒãã£è£œ crate ãå«ãã æ¹æ³ãå«ãŸããŸãã
- ãã¢ã¡ã¿ã«: ãã¢ã¡ã¿ã« (çµã¿èŸŒã¿) éçºã§ Rust ã䜿ãçµæ¥ ã¯ã©ã¹ã§ãããã€ã¯ãã³ã³ãããŒã©ãŒãšã¢ããªã±ãŒã·ã§ã³ããã»ããµãŒã®äž¡æ¹ãæ±ã ãŸãã
- äžŠè¡æ§: Rust ã®äžŠè¡æ§ã«é¢ããçµæ¥ã¯ã©ã¹ã§ããå€å žçãª äžŠè¡æ§ïŒã¹ã¬ãããšãã¥ãŒããã¯ã¹ã䜿çšããããªãšã³ããã£ããªã¹ã±ãžã¥ãŒãªã³ã°ïŒ ãšãasync/await ã«ããäžŠè¡æ§ïŒfuture ã䜿çšããå調çãã«ãã¿ã¹ã¯ïŒã®äž¡æ¹ã æ±ããŸãã
察象å€
Rust ã¯å€§ããªèšèªã§ãããæ°æ¥ã§ãã¹ãŠãæ±ãããšã¯ã§ããŸããã ãã®ã³ãŒã¹ã®å¯Ÿè±¡å€ã®äžéšã¯æ¬¡ã®ãšããã§ã:
- ãã¯ãã®éçºæ¹æ³ãåŠã¶ããš: 代ããã« the Rust Book ãš Rust by Example ãåç §ããŠãã ããã
åæ
ãã®ã³ãŒã¹ã§ã¯ãåè¬è ããã§ã«ããã°ã©ãã³ã°ã®æ¹æ³ãç¥ã£ãŠããããšãåæãšã㊠ããŸããRust ã¯éçåä»ãèšèªã§ãããRust ã®ã¢ãããŒãããããã説æãããå¯Ÿæ¯ ãããããããã«ãC ã C++ ãšæ¯èŒããããšããããŸãã
Python ã JavaScript ã®ãããªåçåä»ãèšèªã§ã®ããã°ã©ãã³ã°æ¹æ³ãç¥ã£ãŠãã ã°ãåé¡ãªãã€ããŠããããšãã§ããã§ãããã
ãã㯠ã¹ããŒã«ãŒããŒã ã®äŸã§ãããããã䜿ã£ãŠã¹ã©ã€ãã«è¿œå ã® æ å ±ãå ããŸããããã«ã¯ãè¬åž«ãåãäžããã¹ãéèŠãªãã€ã³ããã ææ¥ã§ããåºã質åãžã®åçãªã©ãå«ãŸããŸãã
ã³ãŒã¹ã®éå¶
ãã®ããŒãžã¯ã³ãŒã¹ã®è¬åž«åãã§ãã
ããã§ã¯ãGoogle 瀟å ã§ãã®ã³ãŒã¹ãã©ã®ããã«éå¶ããŠãããã«ã€ããŠã èæ¯æ å ±ãå°ã玹ä»ããŸãã
éåžžãè¬çŸ©ã¯åå 9:00 ããååŸ 4:00 ãŸã§å®æœãããã®éã« 1 æéã®æŒäŒã¿ã æã¿ãŸããããã«ãããååã®è¬çŸ©ã« 3 æéãååŸã®è¬çŸ©ã« 3 æéãå ãŠãããšã ã§ããŸããã©ã¡ãã®ã»ãã·ã§ã³ã«ãè€æ°åã®äŒæ©ãšãåè¬è ãæŒç¿ã«åãçµãæéã å«ãŸããŸãã
ã³ãŒã¹ã宿œããåã«ã次ã®ããšãè¡ã£ãŠãããšããã§ãããã
-
ã³ãŒã¹ææã«æ £ããŠãããŠãã ãããéèŠãªãã€ã³ãã匷調ã§ããããã ã¹ããŒã«ãŒããŒããçšæããŠããŸãïŒãã²ã¹ããŒã«ãŒããŒãã®è¿œå ã«ã ãååãã ããïŒïŒãçºè¡šæã«ã¯ãã¹ããŒã«ãŒããŒãããããã¢ããã§ éããŠããããã«ããŠãã ããïŒâSpeaker Notesâ ã®æšªã«ããå°ããªç¢å°ã® ãªã³ã¯ãã¯ãªãã¯ããŸãïŒãããããã°ãã¯ã©ã¹ã«èŠããç»é¢ããã£ãã ä¿ãŠãŸãã
-
æ¥çšã決ããŠãã ããããã®ã³ãŒã¹ã¯ 4 æ¥éãããããã2 é±éã«åã㊠æ¥çšãçµãããšããå§ãããŸããåè¬è ããã¯ãã³ãŒã¹ã®éã«ééããããšã ãã¡ããæäŸããæ å ±ãæŽçãããããªã£ãŠåœ¹ç«ã€ããšãã声ãå¯ããã㊠ããŸãã
-
察é¢åå è ãå容ã§ããååãªåºãã®éšå±ã確ä¿ããŠãã ãããåè¬è æ°ã¯ 15ã25 äººãæšå¥šããŸããããã¯ãåå è ãæ°è»œã«è³ªåã§ããååã«å°ããª èŠæš¡ã§ãããåæã« 1 人ã®è¬åž«ã§ã質åã«çããæéã確ä¿ã§ããèŠæš¡ã§ã ãããŸããéšå±ã«ã¯ãèªåçšãšåè¬è çšã® æº ãããããšã確èªã㊠ãã ãã: å šå¡ã座ã£ãŠããŒã PC ã§äœæ¥ã§ããå¿ èŠããããŸããç¹ã«ã è¬åž«ãšããŠããªãã®éã®ã©ã€ãã³ãŒãã£ã³ã°ãè¡ããããæŒå°ã¯ããŸã 圹ã«ç«ã¡ãŸããã
-
ã³ãŒã¹åœæ¥ã¯ãæºåã®ããã«å°ãæ©ãã«éšå±ã«å ¥ã£ãŠãã ããã ãã¬ãŒã³ããŒã·ã§ã³ã«ã¯ãããŒã PC äžã§åãããŠãã
mdbook serveã çŽæ¥äœ¿ãããšããå§ãããŸãïŒã€ã³ã¹ããŒã«æé ãåç §ã㊠ãã ããïŒãããããããšã§ãããŒãžãåãæ¿ããéã®é å»¶ããªããæé©ãª ããã©ãŒãã³ã¹ã確ä¿ã§ããŸãããŸããèªåã®ããŒã PC ã䜿ãã°ãããªãã åè¬è ã誀åãèŠã€ãããã®å Žã§ä¿®æ£ã§ããŸãã -
æŒç¿ã¯ãåèªãŸãã¯å°äººæ°ã®ã°ã«ãŒãã§è§£ããŠããã£ãŠãã ãããéåžžã ååãšååŸã«ãããã 30ã45 åãæŒç¿ã«å ãŠãŸãïŒè§£çã®æ¯ãè¿ãã®æéã å«ã¿ãŸãïŒãè¡ãè©°ãŸã£ãŠããªãããäœãæäŒããããšã¯ãªãããå¿ ã声ã ãããŠãã ãããè€æ°ã®äººãåãåé¡ã«çŽé¢ããŠããã®ãèŠããããããã® ããšãã¯ã©ã¹å šäœã«å ±æãã解決çã瀺ããŠãã ãããããšãã°ãæšæº ã©ã€ãã©ãªã®ã©ãã«é¢é£æ å ±ããããã瀺ããšããã§ãããã
以äžã§ããã³ãŒã¹éå¶ã®æåãç¥ã£ãŠããŸãïŒ ç§ãã¡ã«ãšã£ãŠããã§ãã£ã ããã«ãããªãã«ãšã£ãŠã楜ãããã®ã«ãªãããšãé¡ã£ãŠããŸãïŒ
ä»åŸãã³ãŒã¹ãæ¹åãç¶ãããããããçµäºåŸã«ãã² ãã£ãŒãããã¯ããå¯ããã ãããããŸããã£ãç¹ããããã«æ¹åã§ãã ç¹ããã²ãèãããã ãããåè¬è ã®çããããã® ãã£ãŒãããã¯ã倧æè¿ã§ãïŒ
è¬åž«ã®æºå
- ãã¹ãŠã®ææã«ç®ãéã: ã³ãŒã¹ãæããåã«ããã¹ãŠã®ã¹ã©ã€ããšæŒç¿ã èªåã§äžéã確èªããŠãããŠãã ãããããããããšã§ã質åãèµ·ãããã 飿ãäºåã«æ³å®ãããããªããŸãã
- ã©ã€ãã³ãŒãã£ã³ã°ã®æºåããã: ãã®ã³ãŒã¹ã§ã¯ã©ã€ãã³ãŒãã£ã³ã°ã ããªãè¡ããŸããææ¥äžã«ã¹ã ãŒãºã«å ¥åã§ãããããäŸé¡ãæŒç¿ã¯äºåã« ç·Žç¿ããŠãããŠãã ãããè¡ãè©°ãŸã£ãå Žåã«åããŠãè§£çãçšæããŠãã ãŸãããã
mdbookã«æ £ããŠãã: ãã®ã³ãŒã¹ã¯mdbookã䜿ã£ãŠé²è¡ããŸãã ç§»åæ¹æ³ãæ€çŽ¢æ¹æ³ãæ©èœã®äœ¿ãæ¹ãææ¡ããŠãããšãé²è¡ãããã¹ã ãŒãºã« ãªããŸãã- 衚瀺é åãã«ããŒ: ãã¬ãŒã³ããŒã·ã§ã³æã«å©çšã§ãã衚瀺é åã瀺ã ããžã¥ã¢ã«ã¬ã€ãã®è¡šç€º/é衚瀺ãåãæ¿ããã«ã¯ãCtrl + Alt + B ãæŒããŸããèµ€ãæ ã®å€ã«ããã³ã³ãã³ãã¯ã æåã¯è¡šç€ºãããªããšèããŠãã ãããã¹ã©ã€ããç·šéãããšãã®ç®å®ãšã㊠䜿ã£ãŠãã ããããã®ãªã³ã¯ããæå¹ã«ããããšãã§ããŸãã
è¯ãåŠç¿ç°å¢ãäœã
- 質åãä¿ã: ããã ããªãã質åã¯ãªãããšãç¹°ãè¿ãäŒããŠãã ããã 質åããããé°å²æ°ã¯åŠç¿ã«ãšã£ãŠéèŠã§ãã
- æéã广çã«ç®¡çãã: ã¹ã±ãžã¥ãŒã«ã¯æèãã€ã€ãæè»ã«å¯Ÿå¿ã㊠ãã ãããã¿ã€ã ã©ã€ã³ã«å³å¯ã«åŸãããšããããåè¬è ãæŠå¿µãçè§£ãã ããšã®ã»ããéèŠã§ãã
- ã°ã«ãŒãäœæ¥ãä¿é²ãã: æŒç¿äžã¯ãåè¬è å士ã§ååããŠåãçµããã ä¿ããŠãã ãããããããããšã§ãäºãã«åŠã³åããè¡ãè©°ãŸãæãæžãã ãŸãã
ã³ãŒã¹æ§æ
ãã®ããŒãžã¯ã³ãŒã¹è¬åž«åãã§ãã
Rust ã®åºç€
æåã® 4 æ¥éã Rust Fundamentals ã«çžåœããŸãã忥ã¯ãã³ãããé²ã¿ãå¹ åºããããã¯ãæ±ããŸãïŒ
not found - {{%course outline Fundamentals}}
æ·±æã
4 æ¥éã® Rust Fundamentals ã«å ããŠãããã«å°éçãªãããã¯ãæ±ããŸãã
Rust in Android
Rust in Android ã®æ·±æãã³ãŒã¹ã¯ãAndroid ãã©ãããã©ãŒã éçºã§ Rust ãäœ¿ãæ¹æ³ãæ±ã忥ã³ãŒã¹ã§ããããã«ã¯ãCãC++ãJava ãšã®çžäºéçšãå«ãŸããŸãã
AOSP ãã§ãã¯ã¢ãŠã ãå¿
èŠã§ããåããã·ã³äžã§ ã³ãŒã¹ãªããžã㪠ããã§ãã¯ã¢ãŠãããsrc/android/ ãã£ã¬ã¯ããªã AOSP ãã§ãã¯ã¢ãŠãã®ã«ãŒãã«ç§»åããŠãã ãããããã«ãããAndroid ãã«ãã·ã¹ãã ã src/android/ å
ã® Android.bp ãã¡ã€ã«ãèªèã§ããããã«ãªããŸãã
ãšãã¥ã¬ãŒã¿ãŸãã¯å®æ©ã§ adb sync ãåäœããããšã確èªããsrc/android/build_all.sh ã䜿ã£ãŠãã¹ãŠã® Android ãµã³ãã«ãäºåã«ãã«ãããŠãã ãããã¹ã¯ãªãããèªãã§ã©ã®ã³ãã³ããå®è¡ããããã確èªããããããæåã§å®è¡ããŠãåäœããããšã確ãããŠãã ããã
Rust in Chromium
Rust in Chromium ã®æ·±æãã³ãŒã¹ã¯ãChromium ãã©ãŠã¶ã®äžéšãšã㊠Rust ãäœ¿ãæ¹æ³ãæ±ã忥ã³ãŒã¹ã§ããããã«ã¯ãChromium ã® gn ãã«ãã·ã¹ãã ã§ Rust ã䜿ãããšããµãŒãããŒãã£ã©ã€ãã©ãªïŒãã¯ã¬ãŒããïŒã®åã蟌ã¿ãC++ ãšã®çžäºéçšãå«ãŸããŸãã
Chromium ããã«ãã§ããå¿ èŠããããŸã â é床ã®é¢ã§ã¯ããããã°çšã® component build ã æšå¥š ãããŸãããã©ã®ãã«ãã§ãåäœããŸãããã«ããã Chromium ãã©ãŠã¶ãå®è¡ã§ããããšã確èªããŠãã ããã
Bare-Metal Rust
Bare-Metal Rust ã®æ·±æãã³ãŒã¹ã¯ããã¢ã¡ã¿ã«ïŒçµã¿èŸŒã¿ïŒéçºã§ Rust ãäœ¿ãæ¹æ³ãæ±ã 1 æ¥ã³ãŒã¹ã§ãããã€ã¯ãã³ã³ãããŒã©ãšã¢ããªã±ãŒã·ã§ã³ããã»ããµã®äž¡æ¹ãæ±ããŸãã
ãã€ã¯ãã³ã³ãããŒã©ã®ããŒãã§ã¯ãäºåã« BBC micro:bit v2 éçºããŒããè³Œå ¥ããŠããå¿ èŠããããŸããå šå¡ã ãŠã§ã«ã«ã ããŒãž ã«èšèŒãããŠãããšããã«ãããã€ãã®ããã±ãŒãžãã€ã³ã¹ããŒã«ããå¿ èŠããããŸãã
Rustã§ã®äžŠè¡æ§
Concurrency in Rust ã®æ·±æãã³ãŒã¹ã¯ãå€å
žçãªäžŠè¡æ§ãš async/await ã«ããäžŠè¡æ§ãæ±ã 1 æ¥ã³ãŒã¹ã§ãã
æ°ããã¯ã¬ãŒããã»ããã¢ããããäŸåé¢ä¿ãããŠã³ããŒãããŠããã«äœ¿ããããã«ããŠããå¿
èŠããããŸãããã®åŸããµã³ãã«ã src/main.rs ã«ã³ããŒïŒããŒã¹ãããŠè©Šãããšãã§ããŸãã
cargo init concurrency
cd concurrency
cargo add tokio --features full
cargo run
not found - {{%course outline Concurrency}}
Idiomatic Rust
Idiomatic Rust ã®æ·±æãã³ãŒã¹ã¯ãRust ã®ã€ãã£ãªã ãšãã¿ãŒã³ãæ±ã 2 æ¥éã®ã³ãŒã¹ã§ãã
ãã®ã³ãŒã¹ãå§ããåã«ãRust Fundamentals ã®å 容ãäžéãçè§£ããŠããã¹ãã§ãã
not found - {{%course outline Idiomatic Rust}}
UnsafeïŒäœæ¥äžïŒ
Unsafe ã®æ·±æãã³ãŒã¹ã¯ãRust èšèªã® unsafe ãæ±ã 2 æ¥éã®ã³ãŒã¹ã§ããRust ã®å®å
šæ§ä¿èšŒã®åºç€ãunsafe ã®å¿
èŠæ§ãunsafe ã³ãŒãã®ã¬ãã¥ãŒæé ãFFI ã®åºç€ããããŠéåžžãªãåçšãã§ãã«ãŒã«æåŠãããããŒã¿æ§é ã®æ§ç¯ãæ±ããŸãã
not found - {{%course outline Unsafe}}
é²ãæ¹
ãã®ã³ãŒã¹ã¯éåžžã«ã€ã³ã¿ã©ã¯ãã£ãã«é²ããããšãæå³ããŠããã質åããã£ããã« Rust ã®æ¢æ±ãé²ããŠããããšããå§ãããŸãïŒ
ããŒããŒãã·ã§ãŒãã«ãã
mdBook ã«ã¯ãããã€ã䟿å©ãªããŒããŒãã·ã§ãŒãã«ããããããŸãã
- Arrow-Left: åã®ããŒãžã«ç§»åããŸãã
- Arrow-Right: 次ã®ããŒãžã«ç§»åããŸãã
- Ctrl + Enter: ãã©ãŒã«ã¹ã®ããã³ãŒããµã³ãã«ãå®è¡ããŸãã
- s: æ€çŽ¢ããŒãã¢ã¯ãã£ãã«ããŸãã
- ãããã®ã·ã§ãŒãã«ããã¯
mdbookã®æšæºæ©èœã§ãããmdbookã§çæããã ãããããµã€ããç§»åãããšãã«åœ¹ç«ã€ããšãäŒããŠãã ããã - åã·ã§ãŒãã«ãããåè¬è ã«ã©ã€ãã§å®æŒã§ããŸãã
- æ€çŽ¢çšã® s ããŒã¯ã以åã«åãäžãããããã¯ããã°ããèŠã€ããã®ã« ç¹ã«äŸ¿å©ã§ãã
- Ctrl + Enter ã¯ãã©ã€ãã³ãŒãã£ã³ã°ãããããè¡ãããšã«ãªãã®ã§ã ããªãã«ãšã£ãŠéåžžã«éèŠã§ãã
翻蚳
ãã®ã³ãŒã¹ã¯ãçŽ æŽããããã©ã³ãã£ã¢ã®æ¹ã ã«ãã£ãŠããŸããŸãªèšèªã« 翻蚳ãããŠããŸã:
- ãã«ãã¬ã«èªïŒãã©ãžã«ïŒ 㯠@rastringer, @hugojacob, @joaovicmendes, @henrif75 ã«ãã翻蚳ã§ãã
- äžåœèªïŒç°¡äœåïŒ ã¯ @suetfei, @wnghl, @anlunx, @kongy, @noahdragon, @superwhd, @SketchK, @nodmp ã«ãã翻蚳ã§ãã
- äžåœèªïŒç¹äœåïŒ ã¯ @hueich, @victorhsieh, @mingyc, @kuanhungchen, @johnathan79717 ã«ãã翻蚳ã§ãã
- ãã«ã·ã¢èª 㯠@DannyRavi, @javad-jafari, @Alix1383, @moaminsharifi, @hamidrezakp, @mehrad77 ã«ãã翻蚳ã§ãã
- æ¥æ¬èª 㯠@CoinEZ-JPN, @momotaro1105, @HidenoriKobayashi, @kantasv ã«ãã翻蚳ã§ãã
- éåœèª 㯠@keispace, @jiyongp, @jooyunghan, @namhyung ã«ãã 翻蚳ã§ãã
- ã¹ãã€ã³èª 㯠@deavid ã«ãã翻蚳ã§ãã
- ãŠã¯ã©ã€ãèª ã¯ @git-user-cpp, @yaremam, @reta ã«ãã翻蚳ã§ãã
å³äžã®èšèªéžæã¡ãã¥ãŒã䜿ã£ãŠãèšèªãåãæ¿ããŠãã ããã
æªå®æã®ç¿»èš³
çŸåšé²è¡äžã®ç¿»èš³ãæ°å€ããããŸããããã§ã¯ãæè¿æŽæ°ããã翻蚳ãžã® ãªã³ã¯ãæ²èŒããŠããŸã:
- ã¢ã©ãã¢èª 㯠@younies ã«ãã翻蚳ã§ãã
- ãã³ã¬ã«èª 㯠@raselmandol ã«ãã翻蚳ã§ãã
- ãã©ã³ã¹èª 㯠@KookaS, @vcaen, @AdrienBaudemont ã«ãã 翻蚳ã§ãã
- ãã€ãèª ã¯ @Throvn, @ronaldfw ã«ãã翻蚳ã§ãã
- ã€ã¿ãªã¢èª 㯠@henrythebuilder, @detro ã«ãã翻蚳ã§ãã
翻蚳ã®å®å šãªäžèЧãšçŸåšã®ç¶æ³ã¯ãæçµæŽæ°æç¹ã®äžèЧ ãŸã㯠ã³ãŒã¹ã®ææ°çã«åæãããäžèЧ ã§ãåç §ã§ããŸãã
ãã®åãçµã¿ã«ååãããå Žåã¯ãå§ãæ¹ã«ã€ã㊠æé ãåç §ã㊠ãã ããã翻蚳ã«é¢ãã調æŽã¯ ã€ã·ã¥ãŒãã©ãã«ãŒ ã§è¡ãããŠããŸãã
- ããã¯ã翻蚳ã«è²¢ç®ããŠããããã©ã³ãã£ã¢ã®æ¹ã ã«æè¬ãäŒãããã æ©äŒã§ãã
- ææ¥ã«äžèšã®ããããã®èšèªã話ãåè¬è ãããå Žåã¯ã翻蚳çã確èªã㊠ã¿ãããå§ããåé¡ãèŠã€ãããè²¢ç®ããŠãããããä¿ããŸãã
- ãã®ãããžã§ã¯ãããªãŒãã³ãœãŒã¹ã§ããã翻蚳ã ãã§ãªãã³ãŒã¹å 容 ãã®ãã®ãžã®è²¢ç®ãæè¿ãããŠããããšã匷調ããŠãã ããã
Cargo ã䜿ã
Rust ã«ã€ããŠèªã¿å§ãããšãããã« Cargo ã«åºäŒãã§ããããããã¯ãRust ãšã³ã·ã¹ãã ã§ Rust ã¢ããªã±ãŒã·ã§ã³ããã«ãããŠå®è¡ããããã«äœ¿ãããæšæºããŒã«ã§ããããã§ã¯ãCargo ãšã¯äœããããåºããšã³ã·ã¹ãã ã®äžã§ã©ã®ãããªäœçœ®ä»ãã«ããã®ãããããŠãã®ãã¬ãŒãã³ã°ã®äžã§ã©ã®ããã«äœçœ®ä»ããããã®ããç°¡åã«æŠèª¬ããŸãã
ã€ã³ã¹ããŒã«
https://rustup.rs/ ã®æé ã«åŸã£ãŠãã ããã
ããã«ãããCargo ãã«ãããŒã« (cargo) ãš Rust ã³ã³ãã€ã© (rustc) ãã€ã³ã¹ããŒã«ãããŸãããŸããç°ãªãã³ã³ãã€ã©ããŒãžã§ã³ãã€ã³ã¹ããŒã«ããããã«äœ¿ããã³ãã³ãã©ã€ã³ãŠãŒãã£ãªã㣠rustup ãå©çšã§ããããã«ãªããŸãã
Rust ãã€ã³ã¹ããŒã«ãããããšãã£ã¿ã IDE ã Rust ã§åäœããããã«èšå®ããã¹ãã§ããã»ãšãã©ã®ãšãã£ã¿ã¯ rust-analyzer ãšé£æºããããšã§ãããå®çŸããŸããrust-analyzer ã¯ãVS CodeãEmacsãVim/Neovim ãªã©å€ãã®ç°å¢åãã«ãèªåè£å®ãå®çŸ©ãžã®ãžã£ã³ãæ©èœãæäŸããŸããRustRover ãšããå¥ã® IDE ãå©çšã§ããŸãã
-
Debian/Ubuntu ã§ã¯ã
aptçµç±ã§rustupãã€ã³ã¹ããŒã«ã§ããŸã:sudo apt install rustup -
macOS ã§ã¯ãRust ã®ã€ã³ã¹ããŒã«ã« Homebrew ã䜿çšã§ããŸãããå€ãããŒãžã§ã³ãæäŸãããå ŽåããããŸãããã®ãããå ¬åŒãµã€ããã Rust ãã€ã³ã¹ããŒã«ããããšãæšå¥šããŸãã
Rust ãšã³ã·ã¹ãã
Rust ãšã³ã·ã¹ãã ã¯å€æ°ã®ããŒã«ã§æ§æãããŠãããäž»ãªãã®ã¯æ¬¡ã®ãšããã§ã:
-
rustc:.rsãã¡ã€ã«ããã€ããªããã®ä»ã®äžé圢åŒã«å€æãã Rust ã³ã³ãã€ã©ã -
cargo: Rust ã®äŸåé¢ä¿ãããŒãžã£ãŒå Œãã«ãããŒã«ãCargo ã¯ã éåžž https://crates.io ã§ãã¹ããããŠããäŸåé¢ä¿ãããŠã³ããŒãã§ãã ãããžã§ã¯ãããã«ããããšãã«ããããrustcã«æž¡ããŸããCargo ã«ã¯ çµã¿èŸŒã¿ã®ãã¹ãã©ã³ããŒãå«ãŸããŠããããŠããããã¹ãã®å®è¡ã«äœ¿ãããŸãã -
rustup: Rust ããŒã«ãã§ãŒã³ã®ã€ã³ã¹ããŒã©ãŒå Œã¢ããããŒã¿ãŒããã®ããŒã«ã¯ã æ°ãã Rust ã®ããŒãžã§ã³ããªãªãŒã¹ããããšãã«rustcãšcargoã ã€ã³ã¹ããŒã«ããã³æŽæ°ããããã«äœ¿çšãããŸããããã«ãrustupã¯æšæº ã©ã€ãã©ãªã®ããã¥ã¡ã³ããããŠã³ããŒãã§ããŸããè€æ°ã® Rust ããŒãžã§ã³ã åæã«ã€ã³ã¹ããŒã«ããŠããããšãã§ããrustupã䜿ã£ãŠå¿ èŠã«å¿ã㊠ããããåãæ¿ããããŸãã
éèŠãªãã€ã³ã:
-
Rust ã¯6é±éããšã«æ°ãããªãªãŒã¹ãåºããšããè¿ éãªãªãªãŒã¹ãµã€ã¯ã«ã æ¡çšããŠããŸããæ°ãããªãªãŒã¹ã¯å€ããªãªãŒã¹ãšã®åŸæ¹äºææ§ãç¶æããŸã â ããã«ãæ°ããæ©èœãå©çšå¯èœã«ããŸãã
-
ãªãªãŒã¹ãã£ãã«ã¯ âstableâãâbetaâãânightlyâ ã®3ã€ã§ãã
-
æ°æ©èœã¯ ânightlyâ ã§ãã¹ããããâbetaâ ã¯6é±éããšã« âstableâ ã« ãªããã®ã§ãã
-
äŸåé¢ä¿ã¯ã代æ¿ã® registriesãgitããã©ã«ããŒãªã©ãã解決ããããšã ã§ããŸãã
-
Rust ã«ã¯ editions ããããŸããçŸåšã®ãšãã£ã·ã§ã³ã¯ Rust 2024 ã§ãã 以åã®ãšãã£ã·ã§ã³ã¯ Rust 2015ãRust 2018ãRust 2021 ã§ããã
-
ãšãã£ã·ã§ã³ã§ã¯ãèšèªã«åŸæ¹äºææ§ã®ãªã倿Žãå ããããšãèªããã㊠ããŸãã
-
ã³ãŒããå£ããã®ãé²ãããããšãã£ã·ã§ã³ã¯ãªããã€ã³æ¹åŒã§ã:
Cargo.tomlãã¡ã€ã«ãéããŠãcrate ã«äœ¿çšãããšãã£ã·ã§ã³ãéžæããŸãã -
ãšã³ã·ã¹ãã ã®åæãé¿ãããããRust ã³ã³ãã€ã©ã¯ç°ãªããšãã£ã·ã§ã³åãã« æžãããã³ãŒããæ··åšãããããšãã§ããŸãã
-
ã³ã³ãã€ã©ã
cargoãä»ããã«çŽæ¥äœ¿ãããšã¯ããªããŸãã§ããããš ïŒã»ãšãã©ã®ãŠãŒã¶ãŒã¯äžåºŠãããããªãããšïŒã«ãè§ŠããŠãã ããã -
Cargo èªäœãéåžžã«åŒ·åã§å æ¬çãªããŒã«ã§ããããšã«è§Šããã®ãããã§ãããã Cargo ã¯ã次ã®ãããªãã®ãå«ãå€ãã®é«åºŠãªæ©èœãåããŠããŸã:
- ãããžã§ã¯ã/ããã±ãŒãžæ§é
- workspacesïŒã¯ãŒã¯ã¹ããŒã¹ïŒ
- éçºäŸåé¢ä¿ããã³å®è¡æäŸåé¢ä¿ã®ç®¡ç/ãã£ãã·ã¥
- build scriptingïŒãã«ãã¹ã¯ãªããïŒ
- global installation
- ãŸãããµãã³ãã³ããã©ã°ã€ã³ã«ããæ¡åŒµãå¯èœã§ãïŒããšãã° cargo clippyïŒã
-
詳ãã㯠official Cargo Book ãåç §ããŠãã ãã
-
ãã®ãã¬ãŒãã³ã°ã®ã³ãŒããµã³ãã«
ãã®ãã¬ãŒãã³ã°ã§ã¯ãäž»ã«ãã©ãŠã¶ããå®è¡ã§ããäŸãéã㊠Rust èšèªã åŠã³ãŸããããã«ããã»ããã¢ãããã¯ããã«ç°¡åã«ãªããå šå¡ã«äžè²«ããäœéšã æäŸã§ããŸãã
Cargo ãã€ã³ã¹ããŒã«ããŠããããšãåŒãç¶ãæšå¥šãããŸããããããããšã§ æŒç¿ãé²ãããããªããŸããæçµæ¥ã«ã¯ãäŸåé¢ä¿ã®æ±ãæ¹ãåŠã¶ããã®ã ãã倧ããªæŒç¿ãè¡ããŸãããã®ããã«ã¯ Cargo ãå¿ èŠã§ãã
ãã®ã³ãŒã¹ã®ã³ãŒããããã¯ã¯å®å šã«ã€ã³ã¿ã©ã¯ãã£ãã§ã:
// èäœæš© 2022 Google LLC // SPDX-License-Identifier: Apache-2.0 fn main() { println!("Edit me!"); }
ããã¹ãããã¯ã¹ã«ãã©ãŒã«ã¹ããããšãã¯ãCtrl + Enter ã§ ã³ãŒããå®è¡ã§ããŸãã
ã»ãšãã©ã®ã³ãŒããµã³ãã«ã¯ãäžã§ç€ºããããã«ç·šéã§ããŸããããã€ãã®ã³ãŒããµã³ãã«ã¯ã ããŸããŸãªçç±ã«ããç·šéã§ããŸãã:
-
åã蟌㿠Playground ã§ã¯ãŠããããã¹ããå®è¡ã§ããŸããããŠããããã¹ãã詊ãã«ã¯ã ã³ãŒããã³ããŒïŒããŒã¹ãããŠå®éã® Playground ã§éããŠãã ããã
-
åã蟌㿠Playground ã¯ãããŒãžããç§»åããç¬éã«ç¶æ ã倱ããŸã! ãã®ããã åè¬è ã¯ããŒã«ã«ã® Rust ã€ã³ã¹ããŒã«ç°å¢ãŸã㯠Playground ã䜿ã£ãŠæŒç¿ã« åãçµãã¹ãã§ãã
Cargo ã䜿ã£ãŠããŒã«ã«ã§ã³ãŒããå®è¡ãã
èªåã®ã·ã¹ãã ã§ã³ãŒãã詊ããŠã¿ããå Žåã¯ããŸã Rust ãã€ã³ã¹ããŒã«ããå¿
èŠããããŸãããããè¡ãã«ã¯ãRust Book ã®æé ã«åŸã£ãŠãã ãããããã«ãããåäœãã rustc ãš cargo ãæã«å
¥ãã¯ãã§ããæ¬çš¿å·çæç¹ã§ã¯ãææ°ã®å®å®ç Rust ãªãªãŒã¹ã®ããŒãžã§ã³çªå·ã¯æ¬¡ã®ãšããã§ãã
% rustc --version
rustc 1.69.0 (84c898d65 2023-04-16)
% cargo --version
cargo 1.69.0 (6e9a83356 2023-04-12)
Rust ã¯åŸæ¹äºææ§ãç¶æããŠãããããããããæ°ããããŒãžã§ã³ã§ã䜿çšã§ããŸãã
ãããŸã§æºåã§ãããããã®ãã¬ãŒãã³ã°ã«ããäŸã® 1 ã€ãã Rust ãã€ããªããã«ãããããã«ãæ¬¡ã®æé ã«åŸã£ãŠãã ããã
-
ã³ããŒãããäŸã®ãCopy to clipboardããã¿ã³ãã¯ãªãã¯ããŸãã
-
cargo new exerciseã䜿ã£ãŠãã³ãŒãçšã®æ°ããexercise/ãã£ã¬ã¯ããªãäœæããŸãã$ cargo new exercise Created binary (application) `exercise` package -
exercise/ã«ç§»åããcargo runã䜿ã£ãŠãã€ããªããã«ãããŠå®è¡ããŸãã$ cd exercise $ cargo run Compiling exercise v0.1.0 (/home/mgeisler/tmp/exercise) Finished dev [unoptimized + debuginfo] target(s) in 0.75s Running `target/debug/exercise` Hello, world! -
src/main.rsã«ããã²ãªåœ¢ã³ãŒããèªåã®ã³ãŒãã«çœ®ãæããŸããããšãã°ãåã®ããŒãžã®äŸã䜿ãå Žåã¯ãsrc/main.rsãæ¬¡ã®ããã«ããŸãã// Copyright 2022 Google LLC // SPDX-License-Identifier: Apache-2.0 fn main() { println!("Edit me!"); } -
cargo runã䜿ã£ãŠãæŽæ°ãããã€ããªããã«ãããŠå®è¡ããŸãã$ cargo run Compiling exercise v0.1.0 (/home/mgeisler/tmp/exercise) Finished dev [unoptimized + debuginfo] target(s) in 0.24s Running `target/debug/exercise` Edit me! -
cargo checkã䜿ããšããããžã§ã¯ãã®ãšã©ãŒããã°ãã確èªã§ããŸããcargo buildã䜿ããšãå®è¡ããã«ã³ã³ãã€ã«ã§ããŸããéåžžã®ãããã°ãã«ãã§ã¯ãåºåã¯target/debug/ã«ãããŸããæé©åããããªãªãŒã¹ãã«ããçæããã«ã¯ãcargo build --releaseã䜿ã£ãŠãã ãããçæå ã¯target/release/ã§ãã -
Cargo.tomlãç·šéããããšã§ããããžã§ã¯ãã«äŸåé¢ä¿ã远å ã§ããŸããcargoã³ãã³ããå®è¡ãããšãäžè¶³ããŠããäŸåé¢ä¿ã¯èªåçã«ããŠã³ããŒãããã³ã³ã³ãã€ã«ãããŸãã
ææ¥ã®åå è ã«ã¯ãCargo ãã€ã³ã¹ããŒã«ããŠããŒã«ã«ã®ãšãã£ã¿ã䜿ãããå§ããŠã¿ãŠãã ããã éåžžã®éçºç°å¢ã䜿ããããã«ãªãããããã®ã»ããäœæ¥ãããããªããŸãã
1æ¥ç®ãžãããã
ãã㯠Rust Fundamentals ã®åæ¥ã§ãã仿¥ã¯å¹ åºãç¯å²ã® ãããã¯ãæ±ããŸãã
- Rust ã®åºæ¬æ§æ: 倿°ãã¹ã«ã©ãŒåãšè€ååãåæåãæ§é äœã åç §ã颿°ãã¡ãœããã
- åãšåæšè«ã
- å¶åŸ¡ãããŒæ§æ: ã«ãŒããæ¡ä»¶åå²ãªã©ã
- ãŠãŒã¶ãŒå®çŸ©å: æ§é äœãšåæåã
ã¹ã±ãžã¥ãŒã«
session outline
åè¬è ã«æ¬¡ã®ç¹ãå¿ããã«äŒããŠãã ããã
- 質åãããã°ããã®å Žã§ããŠãã ãããæåŸãŸã§ãããŠãããªãã§ãã ããã
- ãã®ã¯ã©ã¹ã¯åæ¹åã§é²ããããšãæå³ããŠãããè°è«ã¯å€§ãã«æè¿ãããŸã!
- è¬åž«ãšããŠã¯ãè°è«ãé©åãªç¯å²ã«åãŸãããåªããŠãã ãããã€ãŸãã Rust ãã©ã®ããã«ç©äºãè¡ãããšãä»ã® èšèªã®ããæ¹ãšã®æ¯èŒã«é¢ããè°è«ã«ããŠãã ãããé©åãªãã©ã³ã¹ãèŠã€ããã®ã¯ é£ãããããããŸããããäžæ¹éè¡ã®ã³ãã¥ãã±ãŒã·ã§ã³ãããåå è ã®é¢äžã é«ãããããè¿·ã£ããè°è«ã蚱容ããæ¹åã§èããŠãã ããã
- 質åã«ãã£ãŠãã¹ã©ã€ãããå
ã®å
容ã«ã€ããŠè©±ãããšã«ãªãå¯èœæ§ãé«ãã§ãã
- ããã§ãŸã£ããåé¡ãããŸãã! å埩ã¯åŠç¿ã®éèŠãªäžéšã§ãã ã¹ã©ã€ãã¯ãããŸã§è£å©ã§ãããå¿ èŠã«å¿ããŠèªç±ã«é£ã°ããŠããããšã å¿ããªãã§ãã ããã
忥ã®ãããã¯ãä»ã®èšèªã«ããã察å¿ã¥ãããã Rust ã®ãåºæ¬ãçãªäºæã 瀺ãããšã§ããRust ã®ããé«åºŠãªéšåã¯ããã®åŸã®æ¥ã« æ±ããŸãã
ãããæå®€ã§æããŠããå Žåã¯ãããã§ã¹ã±ãžã¥ãŒã«ã確èªããã®ã«é©ããŠããŸãã åã»ã°ã¡ã³ãã®æåŸã«ã¯æŒç¿ãããããã®åŸã«äŒæ©ããããŸããäŒæ©åŸã«æŒç¿ã®è§£çã æ±ãäºå®ã«ããŠãã ãããããã«èšèŒãããŠããæéã¯ãã³ãŒã¹ã äºå®ã©ããã«é²ããããã®ç®å®ã§ããå¿ èŠã«å¿ããŠæè»ã« 調æŽããŠãã ãã!
Hello, World
segment outline
Rust ãšã¯äœãïŒ
Rust ã¯æ°ããããã°ã©ãã³ã°èšèªã§ã2015 幎㫠1.0 ããªãªãŒã¹ãããŸãã:
- Rust 㯠C++ ãšäŒŒã圹å²ãæ
ãéçã³ã³ãã€ã«èšèªã§ã
rustcã¯ããã¯ãšã³ããšã㊠LLVM ã䜿çšããŸãã
- Rust ã¯å€ãã®ãã©ãããã©ãŒã ãšã¢ãŒããã¯ãã£ããµããŒãããŠããŸã:
- x86, ARM, WebAssembly, âŠ
- Linux, Mac, Windows, âŠ
- Rust ã¯å¹
åºãããã€ã¹ã§äœ¿çšãããŠããŸã:
- ãã¡ãŒã ãŠã§ã¢ãããŒãããŒããŒã
- ã¹ããŒããã£ã¹ãã¬ã€ã
- æºåž¯é»è©±ã
- ãã¹ã¯ãããã
- ãµãŒããŒã
Rust 㯠C++ ãšåãé åã«äœçœ®ããŠããŸã:
- é«ãæè»æ§ã
- é«ãå¶åŸ¡æ§ã
- ãã€ã¯ãã³ã³ãããŒã©ãŒã®ãããªããªãœãŒã¹ãéåžžã«éãããããã€ã¹ã«ãã¹ã±ãŒã«ããŠã³ã§ããŸãã
- ã©ã³ã¿ã€ã ãã¬ããŒãžã³ã¬ã¯ã·ã§ã³ãæã¡ãŸããã
- ããã©ãŒãã³ã¹ãç ç²ã«ããããšãªããä¿¡é Œæ§ãšå®å šæ§ãéèŠããŠããŸãã
Rust ã®å©ç¹
Rust ã®äž»ãªç¹é·:
-
ã³ã³ãã€ã«æã®ã¡ã¢ãªå®å šæ§ - ã¡ã¢ãªãã°ã®å€§ããªåé¡å šäœã ã³ã³ãã€ã«æã«é²æ¢ã§ãã
- æªåæå倿°ããªãã
- äºéè§£æŸããªãã
- è§£æŸåŸäœ¿çšããªãã
NULLãã€ã³ã¿ããªãã- ããã¯è§£é€ãå¿ãããã¥ãŒããã¯ã¹ããªãã
- ã¹ã¬ããéã®ããŒã¿ç«¶åããªãã
- ã€ãã¬ãŒã¿ã®ç¡å¹åããªãã
-
æªå®çŸ©ã®å®è¡æåäœããªã - Rust ã®æãäœãããããæªèŠå®ã®ãŸãŸã« ãªãããšã¯æ±ºããŠãªã
- é åã¢ã¯ã»ã¹ã§ã¯å¢çãã§ãã¯ãè¡ãããã
- æŽæ°ãªãŒããŒãããŒã¯å®çŸ©ãããŠããïŒpanic ãŸãã¯ã©ããã¢ã©ãŠã³ãïŒã
-
ã¢ãã³ãªèšèªæ©èœ - ãã髿°Žæºãªèšèªãšåçã®è¡šçŸåãšäœ¿ããããã åããŠãã
- åæåãšãã¿ãŒã³ãããã³ã°ã
- ãžã§ããªã¯ã¹ã
- ãªãŒããŒãããã®ãªã FFIã
- ãŒãã³ã¹ãæœè±¡åã
- åªããã³ã³ãã€ã©ãšã©ãŒã
- çµã¿èŸŒã¿ã®äŸåé¢ä¿ãããŒãžã£ãŒã
- ãã¹ãã®çµã¿èŸŒã¿ãµããŒãã
- åªãã Language Server Protocol ãµããŒãã
ããã«ã¯ããŸãæéããããªãã§ãã ããããããã®ç¹ã¯ãã¹ãŠãåŸã§ããã«è©³ãã æ±ããŸãã
åè¬è ã«ãã©ã®èšèªã®çµéšãããããå¿ ãå°ããŠãã ãããçãã«å¿ããŠãRust ã® ç°ãªãç¹åŸŽã匷調ã§ããŸã:
-
C ãŸã㯠C++ ã®çµéšãããå Žå: Rust 㯠borrow checker ã«ãã£ãŠã å®è¡æãšã©ãŒ ã®å€§ããªåé¡å šäœãæé€ããŸããC ã C++ ã®ãããªæ§èœã åŸãããŸãããã¡ã¢ãªå®å šæ§ã®åé¡ã¯ãããŸãããããã«ããã¿ãŒã³ãããã³ã°ã çµã¿èŸŒã¿ã®äŸåé¢ä¿ç®¡çã®ãããªæ§æãåããã¢ãã³ãªèšèªã§ããããŸãã
-
Java, Go, Python, JavaScript⊠ã®çµéšãããå Žå: ãããã®èšèªãšåã ã¡ã¢ãªå®å šæ§ã«å ããŠãåæ§ã®é«æ°ŽæºèšèªãããæèŠãåŸãããŸããããã«ã C ã C++ ã®ããã«é«éã§äºæž¬å¯èœãªæ§èœïŒã¬ãŒããžã³ã¬ã¯ã¿ãªãïŒãšã äœã¬ãã«ã®ããŒããŠã§ã¢ãžã®ã¢ã¯ã»ã¹ãåŸãããŸãïŒå¿ èŠã§ããã°ïŒã
ãã¬ã€ã°ã©ãŠã³ã
Rust Playground ã¯ãçã Rust ããã°ã©ã ãå®è¡ããããã®ç°¡åãªæ¹æ³ãæäŸã㊠ããããã®ã³ãŒã¹ã®äŸãæŒç¿ã®åºç€ã«ããªã£ãŠããŸããæåã«è¡šç€ºããã âhello-worldâ ããã°ã©ã ãå®è¡ããŠã¿ãŠãã ããã䟿å©ãªæ©èœãããã€ã ãããŸãã
-
âToolsâ ã®äžã«ãã
rustfmtãªãã·ã§ã³ã䜿ããšãã³ãŒãããæšæºçãªã æ¹æ³ã§æŽåœ¢ã§ããŸãã -
Rust ã«ã¯ãã³ãŒããçæããããã®äž»ãªããããã¡ã€ã«ãã 2 ã€ãããŸã: DebugïŒå®è¡æãã§ãã¯ãå€ããæé©åã¯å°ãªãïŒãš ReleaseïŒå®è¡æãã§ãã¯ãå°ãªãã æé©åãå€ãïŒã§ãããããã¯äžéšã® âDebugâ ããå©çšã§ããŸãã
-
èå³ãããã°ãââŠâ ã®äžã«ãã âASMâ ã䜿ã£ãŠãçæãããã¢ã»ã³ã㪠ã³ãŒããèŠãããšãã§ããŸãã
åè¬è ãäŒæ©ã«å ¥ãéã«ã¯ããã¬ã€ã°ã©ãŠã³ããéããŠå°ã詊ããŠã¿ããã ä¿ããŠãã ãããã³ãŒã¹ã®æ®ãã®æéãã¿ããéãããŸãŸã«ããŠããããã詊ããŠã¿ããã å§ããŠãã ãããããã¯ãRust ã®æé©åãçæãããã¢ã»ã³ããªã«ã€ããŠãã£ãšç¥ããã äžçŽã®åè¬è ã«ãšã£ãŠãç¹ã«åœ¹ç«ã¡ãŸãã
åãšå€
segment outline
Hello, World
æãåçŽãª Rust ããã°ã©ã ã§ãããå€å žç㪠Hello World ããã°ã©ã ããå§ããŸããã:
// Copyright 2024 Google LLC // SPDX-License-Identifier: Apache-2.0 fn main() { println!("Hello ð!"); }
ããã§ãããããš:
- 颿°ã¯
fnã§å®çŸ©ããŸãã main颿°ã¯ããã°ã©ã ã®ãšã³ããªãã€ã³ãã§ãã- ãããã¯ã¯ãC ã C++ ãšåæ§ã«æ³¢ãã£ãã§åºåããŸãã
- æã¯
;ã§çµãããŸãã printlnã¯ãã¯ãã§ãããåŒã³åºãæã®!ã§ç€ºãããŸãã- Rust ã®æåå㯠UTF-8 ã§ãšã³ã³ãŒããããŠãããä»»æã® Unicode æåãå«ããããŸãã
ãã®ã¹ã©ã€ãã¯ãåè¬è ã Rust ã®ã³ãŒãã«æ £ã芪ãããããã«ããããšãç®çãšããŠããŸãããããã ã® 4 æ¥éã§å€§éã®ã³ãŒããèŠãããšã«ãªãã®ã§ããŸãã¯éŠŽæã¿ã®ããå°ããªãã®ããå§ããŸãã
éèŠãªãã€ã³ã:
-
Rust ã¯ãC/C++/Java ã®ç³»èã«ããä»ã®èšèªã«ãã䌌ãŠããŸããåœä»€åã®èšèªã§ããã 絶察ã«å¿ èŠã§ãªãéãç©äºãäœãçŽãããšã¯ããŸããã
-
Rust ã¯ã¢ãã³ã§ãUnicode ãå®å šã«ãµããŒãããŠããŸãã
-
Rust ã§ã¯ãå¯å€åã®åŒæ°ãåãããå Žé¢ã§ãã¯ãã䜿ããŸãïŒé¢æ°ã® ãªãŒããŒããŒãã¯ãããŸããïŒã
-
println!ããã¯ããªã®ã¯ãéåžžã®é¢æ°ã§ã¯å®çŸã§ããªããæžåŒæååã«å¿ããä»»æåã® åŒæ°ãæ±ãå¿ èŠãããããã§ãããã以å€ã®ç¹ã§ã¯ãéåžžã®é¢æ°ã®ããã«æ±ããŸãã -
Rust ã¯ãã«ããã©ãã€ã ã§ããããšãã°ã匷å㪠ãªããžã§ã¯ãæåããã°ã©ãã³ã°æ©èœ ãåããŠããããŸãã颿°åèšèªã§ã¯ãªããã®ã®ãããŸããŸãª 颿°åã®æŠå¿µ ãåãå ¥ããŠããŸãã
倿°
Rust ã¯éçåä»ãã«ãã£ãŠåå®å
šæ§ãæäŸããŸãã倿°æçžã¯ let ã§è¡ããŸãã
// èäœæš© 2023 Google LLC // SPDX-License-Identifier: Apache-2.0 fn main() { let x: i32 = 10; println!("x: {x}"); // x = 20; // println!("x: {x}"); }
-
x = 20ã®ã³ã¡ã³ããå€ããŠã倿°ãããã©ã«ãã§äžå€ã§ããããšã確èªããŸãããã 倿Žãèš±å¯ããã«ã¯ãmutããŒã¯ãŒãã远å ããŸãã -
ãã®ã¹ã©ã€ãã§ã¯ãæªäœ¿çšå€æ°ãäžèŠãª
mutãªã©ã«å¯ŸããèŠåãæå¹ã«ãªã£ãŠããŸãã ããããèŠåã¯æ³šæãããããªãããã«ãã»ãšãã©ã®ã¹ã©ã€ãã§ã¯çç¥ãããŠããŸãã 倿Žãåé€ããŠãmutããŒã¯ãŒãã ããæ®ããŠã¿ãŠãã ããã -
ããã§ã®
i32ã¯å€æ°ã®åã§ããããã¯ã³ã³ãã€ã«æã«ããã£ãŠããå¿ èŠããããŸããã åæšè«ïŒåŸã§æ±ããŸãïŒã«ãããå€ãã®å Žåã¯ããã°ã©ãããããçç¥ã§ããŸãã
å€
以äžã¯ãåºæ¬çãªçµã¿èŸŒã¿åãšãååã®ãªãã©ã«å€ã®æ§æã§ãã
| å | ãªãã©ã« | |
|---|---|---|
| 笊å·ä»ãæŽæ° | i8ãi16ãi32ãi64ãi128ãisize | -10ã0ã1_000ã123_i64 |
| 笊å·ãªãæŽæ° | u8ãu16ãu32ãu64ãu128ãusize | 0ã123ã10_u16 |
| æµ®åå°æ°ç¹æ° | f32ãf64 | 3.14ã-10.0e20ã2_f32 |
| Unicode ã¹ã«ã©ãŒå€ | char | 'a'ã'α'ã'â' |
| çåœå€ | bool | trueãfalse |
ååã®ãããå¹ ã¯æ¬¡ã®ãšããã§ãã
iNãuNãfN㯠N ãããå¹ ã§ããisizeãšusizeã¯ãã€ã³ã¿ã®å¹ ã§ããchar㯠32 ãããå¹ ã§ããbool㯠8 ãããå¹ ã§ãã
äžã«ã¯ç€ºããŠããªãæ§æãããã€ããããŸãã
- æ°å€äžã®ã¢ã³ããŒã¹ã³ã¢ã¯ãã¹ãŠçç¥ã§ããŸãããããã¯å¯èªæ§ã®ããã ãã®ãã®ã§ãããããã£ãŠã
1_000ã¯1000ïŒãŸãã¯10_00ïŒãšæžãããšãã§ãã123_i64ã¯123i64ãšæžãããšãã§ããŸãã
ç®è¡
// èäœæš© 2023 Google LLC // SPDX-License-Identifier: Apache-2.0 fn interproduct(a: i32, b: i32, c: i32) -> i32 { return a * b + b * c + c * a; } fn main() { println!("result: {}", interproduct(120, 100, 248)); }
ããã¯ãmain 以å€ã®é¢æ°ãåããŠèŠãå Žé¢ã§ããããã®æå³ã¯æãããªã¯ã ã§ãã3 ã€ã®æŽæ°ãåãåããæŽæ°ãè¿ããŸãã颿°ã«ã€ããŠã¯ãåŸã§ãã㫠詳ããæ±ããŸãã
ç®è¡ã¯ãåªå é äœãå«ããŠãä»ã®èšèªãšéåžžã«ãã䌌ãŠããŸãã
ã§ã¯ãæŽæ°ãªãŒããŒãããŒã¯ã©ãã§ãããããC ããã³ C++ ã§ã¯ã笊å·ä»ã æŽæ°ã®ãªãŒããŒãããŒã¯å®éã«ã¯æªå®çŸ©ã§ãããå®è¡æã«äœãèµ·ããã ããããŸãããRust ã§ã¯ãããã¯å®çŸ©ãããŠããŸãã
i32 ã i16 ã«å€æŽããŠãæŽæ°ãªãŒããŒãããŒã確èªããŠã¿ãŠãã ããããã ã¯ããããã°ãã«ãã§ã¯ãããã¯ãïŒãã§ãã¯ããïŒããªãªãŒã¹ãã«ãã§ã¯ å€ãæãè¿ããŸããã»ãã«ããoverflowingãsaturatingãcarrying ãšãã£ã éžæè¢ããããŸãããããã¯ã¡ãœããæ§æã§å©çšã§ããããšãã° (a * b).saturating_add(b * c).saturating_add(c * a) ã®ããã«æžããŸãã
å®éãã³ã³ãã€ã©ã¯å®æ°åŒã®ãªãŒããŒãããŒãæ€åºããŸãããã®ããã ãã®äŸã§ã¯å¥åã®é¢æ°ãå¿ èŠã«ãªããŸãã
åæšè«
Rust ã¯ã倿°ãã©ã®ãã㫠䜿ãããã ãèŠãŠåãæ±ºå®ããŸãã
// Copyright 2023 Google LLC // SPDX-License-Identifier: Apache-2.0 fn takes_u32(x: u32) { println!("u32: {x}"); } fn takes_i8(y: i8) { println!("i8: {y}"); } fn main() { let x = 10; let y = 20; takes_u32(x); takes_i8(y); // takes_u32(y); }
ãã®ã¹ã©ã€ãã§ã¯ã倿°å®£èšãšãã®äœ¿çšã«ãã£ãŠäžããããå¶çŽã«åºã¥ããŠãRust ã³ã³ãã€ã©ãã©ã®ããã«åãæšè«ãããã瀺ããŸãã
ãã®ããã«å®£èšããã倿°ããããããããŒã¿ãä¿æã§ããäœããã®åçãªãä»»æã®åãã§ããããã§ã¯ãªãããšãã匷調ããã®ã¯éåžžã«éèŠã§ãããããã宣èšã«ãã£ãŠçæãããæ©æ¢°èªã³ãŒãã¯ãåãæç€ºãã宣èšã«ãã£ãŠçæããããã®ãšåäžã§ããã³ã³ãã€ã©ããã®äœæ¥ã代ããã«è¡ã£ãŠããããããããç°¡æœãªã³ãŒããæžãããšãã§ããŸãã
æŽæ°ãªãã©ã«ã®åãå¶çŽãããã®ãäœããªãå ŽåãRust ã¯ããã©ã«ãã§ i32 ã䜿çšããŸããããã¯ããšã©ãŒã¡ãã»ãŒãžã§ã¯ {integer} ãšè¡šç€ºãããããšããããŸããåæ§ã«ãæµ®åå°æ°ç¹ãªãã©ã«ã®ããã©ã«ã㯠f64 ã§ãã
// Copyright 2023 Google LLC // SPDX-License-Identifier: Apache-2.0 fn main() { let x = 3.14; let y = 20; assert_eq!(x, y); // ãšã©ãŒ: `{float} == {integer}` ã«å¯Ÿããå®è£ ããããŸãã }
æŒç¿: ãã£ãããã
ãã£ããããæ°å㯠[0, 1] ããå§ãŸããŸããn > 1 ã®å Žåãæ¬¡ã®æ°ã¯çŽåã® 2 ã€ã®æ°ã®åã§ãã
n çªç®ã®ãã£ããããæ°ãèšç®ãã颿° fib(n) ãæžããŠãã ããããã®é¢æ°ã¯ã〠panic ããŸããïŒ
// Copyright 2023 Google LLC // SPDX-License-Identifier: Apache-2.0 fn fib(n: u32) -> u32 { if n < 2 { // ããŒã¹ã±ãŒã¹ã return todo!("ãããå®è£ ããŠãã ãã"); } else { // ååž°ã±ãŒã¹ã return todo!("ãããå®è£ ããŠãã ãã"); } } fn main() { let n = 20; println!("fib({n}) = {}", fib(n)); }
- ãã®æŒç¿ã¯ãååž°ã®å€å žçãªå ¥éã§ãã
- åè¬è ã«ãããŒã¹ã±ãŒã¹ãšååž°ã¹ãããã«ã€ããŠèããããä¿ããŠãã ããã
- ããã®é¢æ°ã¯ã〠panic ããŸããïŒããšããåãã¯ãæŽæ°ãªãŒããŒãããŒã«ã€ããŠèããããã®ãã³ãã§ãããã£ããããæ°åã¯æ¥éã«å€§ãããªããŸãïŒ
- åè¬è ã¯å埩çãªè§£æ³ãæãã€ããããããŸãããããã¯ãååž°ãšå埩ã®ãã¬ãŒããªãïŒäŸ: ããã©ãŒãã³ã¹ãæ·±ãååž°ã§ã®ã¹ã¿ãã¯ãªãŒããŒãããŒïŒã«ã€ããŠè°è«ããçµ¶å¥œã®æ©äŒã§ãã
è§£ç
// èäœæš© 2023 Google LLC // SPDX-License-Identifier: Apache-2.0 fn fib(n: u32) -> u32 { if n < 2 { return n; } else { return fib(n - 1) + fib(n - 2); } } fn main() { let n = 20; println!("fib({n}) = {}", fib(n)); }
ããã§ã¯ã颿°ããå€ãè¿ãããã« return æ§æã䜿ã£ãŠããŸããè¬åº§ã®åŸåã§ã¯ã ãããã¯å
ã®æåŸã®åŒãèªåçã«è¿ãããããšãåŠã³ãŸããããã«ãããããç°¡æœãª ã¹ã¿ã€ã«ã®ããã« return ããŒã¯ãŒããçç¥ã§ããããã«ãªããŸãã
if ã®æ¡ä»¶ n < 2 ã«ã¯æ¬åŒ§ã¯äžèŠã§ããã㯠Rust ã®æšæºç㪠ã¹ã¿ã€ã«ã§ãã
ãããã¯
ãã®æŒç¿ã§ã¯ããã®é¢æ°ããã€ãããã¯ããããåããŸãããã£ããããæ°å㯠éåžžã«æ¥éã«å¢å ããŸããu32 ã§ã¯ãn ã 48 ã«éãããšãèšç®ãããå€ã¯ 32 ãããæŽæ°ã®äžé (4,294,967,295) ããªãŒããŒãããŒããŸãã
Rust ã§ã¯ãæŽæ°æŒç®ã¯ ãããã°ã¢ãŒãïŒcargo run ã䜿ããšãã® ããã©ã«ãïŒã§ãªãŒããŒãããŒãæ€æ»ããŸãããªãŒããŒãããŒãçºçãããšã ããã°ã©ã ã¯ãããã¯ãïŒãšã©ãŒã¡ãã»ãŒãžã衚瀺ããŠã¯ã©ãã·ã¥ãïŒãŸãã ãªãªãŒã¹ã¢ãŒãïŒcargo run --releaseïŒã§ã¯ããªãŒããŒãããŒãã§ãã¯ã¯ ããã©ã«ãã§ç¡å¹ã«ãªã£ãŠãããå€ã¯ã©ããã¢ã©ãŠã³ãã ïŒã¢ãžã¥ã©ãŒæŒç®ïŒã誀ã£ãçµæãçæããŸãã
- è§£çãã¹ãããããšã«ãã©ã£ãŠãã ããã
- ååž°åŒã³åºããšãããããã©ã®ããã«æçµçµæã«ã€ãªãããã説æããŠãã ããã
- æŽæ°ãªãŒããŒãããŒã®åé¡ã«ã€ããŠè°è«ããŠãã ããã
u32ã§ã¯ããã®é¢æ°ã¯nã 47 ååŸã§ãããã¯ããŸããmainãžã®å ¥åã倿Žããããšã§ã ããã宿Œã§ããŸãã - 代æ¿ãšããŠå埩çãªè§£æ³ã瀺ãããã®æ§èœãšã¡ã¢ãªäœ¿çšéãååž°çãªãã®ãšæ¯èŒããŠãã ããã å埩çãªè§£æ³ã®æ¹ãã¯ããã«å¹ççã§ãã
ããã«åŠã¶
ããçºå±çãªè°è«ãšããŠãååž°çãªãã£ããããèšç®ãæé©åããããã«ã¡ã¢åãåç èšç»æ³ã玹ä»ã§ããŸãããããã¯çŸåšã®ãããã¯ã®ç¯å²ãè¶ ããŠããŸãã
å¶åŸ¡ãããŒã®åºæ¬
segment outline
-
ãããããRust ã«ããããŸããŸãªçš®é¡ã®ãããŒå¶åŸ¡ãèŠãŠãããŸãã
-
ãã®å€ãã¯ãä»ã®ããã°ã©ãã³ã°èšèªã§ãã§ã«èŠãããšã®ãããã®ã« éåžžã«ãã䌌ãŠããŸãã
ãããã¯ãšã¹ã³ãŒã
- Rust ã®ãããã¯ã«ã¯ãæ³¢ãã£ã
{}ã§å²ãŸããäžé£ã®åŒãå«ãŸããŸãã - ãããã¯ã®æåŸã®åŒã«ãã£ãŠããããã¯å šäœã®å€ãšåã æ±ºãŸããŸãã
// Copyright 2023 Google LLC // SPDX-License-Identifier: Apache-2.0 fn main() { let z = 13; let x = { let y = 10; dbg!(y); z - y }; dbg!(x); // dbg!(y); }
æåŸã®åŒã ; ã§çµããå Žåãçµæã®å€ãšå㯠() ã«ãªããŸãã
倿°ã®ã¹ã³ãŒãã¯ããããå²ããããã¯å ã«éå®ãããŸãã
-
dbg! ã¯ãææ©ããããã°ã®ããã«ãäžããããåŒã®å€ãåºåããŠè¿ã Rust ãã¯ãã§ãããšèª¬æã§ããŸãã
-
ãããã¯å ã®æåŸã®è¡ã倿Žãããšããããã¯ã®å€ãã©ã®ããã«å€ãããã 瀺ããŸããããšãã°ãã»ãã³ãã³ã远å /åé€ãããã
returnã䜿ã£ããããå Žåã§ãã -
ã¹ã³ãŒãã®å€ã§
yã«ã¢ã¯ã»ã¹ããããšãããšã³ã³ãã€ã«ã§ããªãããšã 宿Œã§ããŸãã -
å€ã¯ããã®ã¹ã¿ãã¯äžã®ããŒã¿ããŸã æ®ã£ãŠããŠããã¹ã³ãŒããå€ãããš å®è³ªçã«ãè§£æŸããããŸãã
if åŒ
if åŒ ã¯ãä»ã®èšèªã® if æãšãŸã£ããåãããã«äœ¿çšããŸãã
// èäœæš© 2024 Google LLC // SPDX-License-Identifier: Apache-2.0 fn main() { let x = 10; if x == 0 { println!("zero!"); } else if x < 100 { println!("biggish"); } else { println!("huge"); } }
ããã«ãif ã¯åŒãšããŠã䜿çšã§ããŸããåãããã¯ã®æåŸã®åŒãã if åŒã®å€ã«ãªããŸãã
// èäœæš© 2024 Google LLC // SPDX-License-Identifier: Apache-2.0 fn main() { let x = 10; let size = if x < 20 { "small" } else { "large" }; println!("number size: {}", size); }
if ã¯åŒã§ãããç¹å®ã®åãæã€å¿
èŠãããããããã®äž¡æ¹ã®åå²ãããã¯ã¯ åãåã§ãªããã°ãªããŸããã2 ã€ç®ã®äŸã§ "small" ã®åŸã« ; ã远å ãããš ã©ããªããã確èªããŠãã ããã
if åŒã¯ãä»ã®åŒãšåãããã«äœ¿çšããå¿
èŠããããŸããããšãã°ã let æã§äœ¿çšããå Žåããã®æã ; ã§çµãã£ãŠããªããã°ãªããŸããã println! ã®åã® ; ãåé€ããŠãã³ã³ãã€ã©ãšã©ãŒã確èªããŠãã ããã
match åŒ
match ã¯ãå€ã1ã€ä»¥äžã®éžæè¢ãšç
§åããããã«äœ¿çšã§ããŸã:
// Copyright 2024 Google LLC // SPDX-License-Identifier: Apache-2.0 fn main() { let val = 1; match val { 1 => println!("one"), 10 => println!("ten"), 100 => println!("one hundred"), _ => { println!("something else"); } } }
if åŒãšåæ§ã«ãmatch ãå€ãè¿ãããšãã§ããŸãã
// Copyright 2024 Google LLC // SPDX-License-Identifier: Apache-2.0 fn main() { let flag = true; let val = match flag { true => 1, false => 0, }; println!("The value of {flag} is {val}"); }
-
matchã®ã¢ãŒã ã¯äžããäžãžé ã«è©äŸ¡ãããäžèŽããæåã®ãã®ã« 察å¿ããæ¬äœãå®è¡ãããŸãã -
ä»ã®èšèªã®
switchã®ãããªã±ãŒã¹éã®ãã©ãŒã«ã¹ã«ãŒã¯ ãããŸããã -
matchã¢ãŒã ã®æ¬äœã¯ãåäžã®åŒã«ããããã¯ã«ãã§ããŸããå³å¯ã«ã¯ ãããã¯ãåŒã§ããããããã¯åãããšã§ãããçŸæç¹ã§ã¯åè¬è 㯠ãã®å¯Ÿç§°æ§ããŸã å®å šã«ã¯çè§£ããŠããªããããããŸããã -
matchåŒã¯ç¶²çŸ çã§ããå¿ èŠããããŸããã€ãŸãããã¹ãŠã®å¯èœãªå€ã ã«ããŒãããã_ã®ãããªããã©ã«ãã±ãŒã¹ãæã€å¿ èŠããããŸãã ç¶²çŸ æ§ã¯åæåã§ç€ºãã®ãæãç°¡åã§ãããåæåã¯ãŸã å°å ¥ãã㊠ããŸããã代ããã«ãæãåçŽãªããªããã£ãåã§ããboolã«å¯Ÿãã ãããã瀺ããŠããŸãã -
ãã®ã¹ã©ã€ãã§ã¯ããã¿ãŒã³ãããã«ã€ããŠè§Šããã«
matchã玹ä»ãã åè¬è ãæåããæ å ±ãè©°ã蟌ã¿ãããããšãªãæ§æã«æ £ããæ©äŒã äžããŠããŸãããã¿ãŒã³ãããã«ã€ããŠã¯ææ¥ãã詳ããæ±ãã®ã§ã ããã§ã¯ããŸã詳ããç«ã¡å ¥ããªãããã«ããŠãã ããã
ããã«æ¢ã
-
matchã䜿ãåæ©ãããã«ç€ºãããã«ããããã®äŸãifã§æžãã ç䟡ãªã³ãŒããšæ¯èŒã§ããŸãã2ã€ç®ã®äŸã§ã¯ãboolã«å¯Ÿãããããã¯ãif {} else {}ãããã¯ãšããªã䌌ãŠããŸããããããè€æ°ã®ã±ãŒã¹ã 調ã¹ãæåã®äŸã§ã¯ãmatchåŒã®ã»ããif {} else if {} else if {} elseããç°¡æœã«æžããŸãã -
matchã¯ãããã¬ãŒãããµããŒãããŠãããããã«ããä»»æã® è«çæ¡ä»¶ã远å ããŠããã®matchã¢ãŒã ãéžæãã¹ããã©ããã è©äŸ¡ã§ããŸãããã ãããããã¬ãŒãã説æããã«ã¯ãã¿ãŒã³ ãããã«ã€ããŠèª¬æããå¿ èŠãããããã®ã¹ã©ã€ãã§ã¯ãããé¿ããããš èããŠããŸãã
ã«ãŒã
Rust ã«ã¯ãwhileãloopãfor ãšãã 3 ã€ã®ã«ãŒãçšããŒã¯ãŒãããããŸã:
while
while ããŒã¯ãŒã ã¯ä»ã®èšèªã®å Žåãšã»ãŒåãããã«åäœããæ¡ä»¶ãçã§ããéãã«ãŒãæ¬äœã å®è¡ããŸãã
// èäœæš© 2023 Google LLC // SPDX-License-Identifier: Apache-2.0 fn main() { let mut x = 200; while x >= 10 { x = x / 2; } dbg!(x); }
for
for ã«ãŒã ã¯ãå€ã®ç¯å²ãŸã㯠ã³ã¬ã¯ã·ã§ã³å
ã®èŠçŽ ãå埩åŠçããŸã:
// èäœæš© 2024 Google LLC // SPDX-License-Identifier: Apache-2.0 fn main() { for x in 1..5 { dbg!(x); } for elem in [2, 4, 8, 16, 32] { dbg!(elem); } }
- å
éšã§ã¯ã
forã«ãŒãã¯ããŸããŸãªçš®é¡ã®ç¯å²ãã³ã¬ã¯ã·ã§ã³ã å埩åŠçããããã«ããã€ãã¬ãŒã¿ããšåŒã°ããæŠå¿µã䜿çšããŸããã€ãã¬ãŒã¿ã«ã€ããŠã¯ åŸã§è©³ãã説æããŸãã - æåã®
forã«ãŒãã¯4ãŸã§ããå埩ããªãããšã«æ³šæããŠãã ãããå å«ç¯å²ã 衚ã1..=5æ§æã瀺ããŠãã ããã
loop
loop æã¯ãbreak ãããŸã§ ã²ãããã«ãŒããç¶ããŸãã
// Copyright 2024 Google LLC // SPDX-License-Identifier: Apache-2.0 fn main() { let mut i = 0; loop { i += 1; dbg!(i); if i > 100 { break; } } }
loopæã¯while trueã«ãŒãã®ããã«åäœããŸããæ¥ç¶ãæ°žç¶çã«åŠçãç¶ãã ãµãŒããŒã®ãããªãã®ã«äœ¿ããŸãã
break ãš continue
次ã®ã€ãã¬ãŒã·ã§ã³ãããã«éå§ãããå Žåã¯ã continue ã䜿çšããŸãã
äœããã®çš®é¡ã®ã«ãŒããéäžã§æãããå Žåã¯ã break ã䜿çšããŸãã loop ã§ã¯ãããã«çç¥å¯èœãªåŒãæå®ã§ãããã®åŒã loop åŒã®å€ã«ãªããŸãã
// Copyright 2023 Google LLC // SPDX-License-Identifier: Apache-2.0 fn main() { let mut i = 0; loop { i += 1; if i > 5 { break; } if i % 2 == 0 { continue; } dbg!(i); } }
ãªããloop ã¯éèªæãªå€ãè¿ããå¯äžã®ã«ãŒãæ§æã§ãã ããã¯ãbreak æã§ã®ã¿è¿ãããšãä¿èšŒãããŠããããã§ã ïŒæ¡ä»¶ãæºããããªããªã£ããšãã«ãè¿ã while ã«ãŒãã for ã«ãŒããšã¯ç°ãªããŸãïŒã
ã©ãã«
continue ãš break ã¯ã©ã¡ããããã¹ãããã«ãŒããæããããã«äœ¿ã çç¥å¯èœãªã©ãã«åŒæ°ãåãåããŸã:
// èäœæš© 2024 Google LLC // SPDX-License-Identifier: Apache-2.0 fn main() { let s = [[5, 6, 7], [8, 9, 10], [21, 15, 32]]; let mut elements_searched = 0; let target_value = 10; 'outer: for i in 0..=2 { for j in 0..=2 { elements_searched += 1; if s[i][j] == target_value { break 'outer; } } } dbg!(elements_searched); }
- ã©ãã«ä»ã break ãä»»æã®ãããã¯ã§æ©èœããŸããããšãã°æ¬¡ã®ãšããã§ãã
#![allow(unused)] fn main() { // èäœæš© 2024 Google LLC // SPDX-License-Identifier: Apache-2.0 'label: { break 'label; println!("This line gets skipped"); } }
颿°
// Copyright 2023 Google LLC // SPDX-License-Identifier: Apache-2.0 fn gcd(a: u32, b: u32) -> u32 { if b > 0 { gcd(b, a % b) } else { a } } fn main() { dbg!(gcd(143, 52)); }
- 宣èšã§ã¯ããã©ã¡ãŒã¿ã®åŸã«åãæžãïŒäžéšã®ããã°ã©ãã³ã°èšèªãšã¯éïŒãæ¬¡ã«æ»ãå€ã®åãæžããŸãã
- 颿°æ¬äœïŒãŸãã¯ä»»æã®ãããã¯ïŒã®æåŸã®åŒãæ»ãå€ã«ãªããŸããåŒã®æ«å°Ÿã®
;ãçç¥ããã ãã§ããæ©æãªã¿ãŒã³ã«ã¯returnããŒã¯ãŒãã䜿çšã§ããŸããã颿°ã®æ«å°Ÿã§ã¯ãå€ã ããæžãã圢åŒãæ £çšçã§ãïŒgcdãreturnã䜿ãããã«ãªãã¡ã¯ã¿ãªã³ã°ããŠã¿ãŠãã ããïŒã - äžéšã®é¢æ°ã«ã¯æ»ãå€ããªããããŠãããåãã§ãã
()ãè¿ããŸããæ»ãå€ã®åãçç¥ããå Žåãã³ã³ãã€ã©ããããæšè«ããŸãã - ãªãŒããŒããŒãã¯ãµããŒããããŠããŸãã â å颿°ã«å®è£
㯠1 ã€ã ãã§ãã
- åžžã«åºå®åæ°ã®ãã©ã¡ãŒã¿ãåããŸããããã©ã«ãåŒæ°ã¯ãµããŒããããŠããŸãããå¯å€é·é¢æ°ããµããŒãããããã«ãã¯ãã䜿ãããšã¯ã§ããŸãã
- åžžã« 1 çµã®ãã©ã¡ãŒã¿åã ããåããŸãããããã®åã¯ãžã§ããªãã¯ã«ããããšãã§ããããã«ã€ããŠã¯åŸã§æ±ããŸãã
ãã¯ã
ãã¯ãã¯ã³ã³ãã€ã«æã« Rust ã³ãŒããžå±éãããå¯å€åã®åŒæ°ãåãããšãã§ããŸããæ«å°Ÿã« ! ãä»ãããšã§åºå¥ãããŸããRust ã® æšæºã©ã€ãã©ãªã«ã¯ã䟿å©ãªãã¯ããããã€ãå«ãŸããŠããŸãã
println!(format, ..)ã¯æšæºåºåã« 1 è¡åºåããstd::fmtã§èª¬æãããŠãã æžåŒèšå®ãé©çšããŸããformat!(format, ..)ã¯println!ãšåæ§ã«åäœããŸãããçµæã æååãšããŠè¿ããŸããdbg!(expression)ã¯åŒã®å€ããã°ã«åºåãããããè¿ããŸããtodo!()ã¯ã³ãŒãã®äžéšãæªå®è£ ãšããŠç€ºããŸããå®è¡ããããš panic ããŸãã
// Copyright 2023 Google LLC // SPDX-License-Identifier: Apache-2.0 fn factorial(n: u32) -> u32 { let mut product = 1; for i in 1..=n { product *= dbg!(i); } product } fn fizzbuzz(n: u32) -> u32 { todo!() } fn main() { let n = 4; println!("{n}! = {}", factorial(n)); }
ãã®ã»ã¯ã·ã§ã³ã®èŠç¹ã¯ããã®ãããªäžè¬çã§äŸ¿å©ãªæ©èœãååšããããšãšããã®äœ¿ãæ¹ã§ãããªããããããã¯ããšããŠå®çŸ©ãããŠããã®ãããŸãäœã«å±éãããã®ãã¯ãç¹ã«éèŠã§ã¯ãããŸããã
ãã®ã³ãŒã¹ã§ã¯ãã¯ãã®å®çŸ©ã¯æ±ããŸããããåŸã®ã»ã¯ã·ã§ã³ã§ derive ãã¯ãã®äœ¿ãæ¹ã説æããŸãã
ããã«èª¿ã¹ã
æšæºã©ã€ãã©ãªã«ã¯ãã»ãã«ã䟿å©ãªãã¯ããããã€ãçšæãããŠããŸããããã«ç¥ãããåŠçãšå ±æã§ãããã»ãã®äŸãããã€ãæããŸãã
assert!ãšé¢é£ãããã¯ãã¯ãã³ãŒãã«ã¢ãµãŒã·ã§ã³ã远å ããããã«äœ¿çšã§ããŸãã ãããã¯ãã¹ããæžãéã«å€çšãããŸããunreachable!ã¯ãå¶åŸ¡ãããŒã®äžã§æ±ºããŠå°éããªãã¯ãã®åå²ã瀺ãããã«äœ¿çšãããŸããeprintln!ã䜿ããš stderr ã«åºåã§ããŸãã
æŒç¿: ã³ã©ããæ°å
ã³ã©ããæ°å ã¯ã0ãã倧ããä»»æã® n1 ã«å¯ŸããŠã次ã®ããã«å®çŸ©ãããŸã:
- ni ã 1 ã§ããã°ãæ°å㯠ni ã§çµäºããŸãã
- ni ãå¶æ°ã§ããã°ãni+1 = ni / 2 ãšãªããŸãã
- ni ã奿°ã§ããã°ãni+1 = 3 * ni + 1 ãšãªããŸãã
ããšãã°ãn1 = 3 ããå§ãããš:
- 3 ã¯å¥æ°ãªã®ã§ãn2 = 3 * 3 + 1 = 10;
- 10 ã¯å¶æ°ãªã®ã§ãn3 = 10 / 2 = 5;
- 5 ã¯å¥æ°ãªã®ã§ãn4 = 3 * 5 + 1 = 16;
- 16 ã¯å¶æ°ãªã®ã§ãn5 = 16 / 2 = 8;
- 8 ã¯å¶æ°ãªã®ã§ãn6 = 8 / 2 = 4;
- 4 ã¯å¶æ°ãªã®ã§ãn7 = 4 / 2 = 2;
- 2 ã¯å¶æ°ãªã®ã§ãn8 = 1; ãããŠ
- æ°åã¯çµäºããŸãã
äžããããåæ n ã«å¯Ÿããã³ã©ããæ°åã®é·ããèšç®ãã颿°ã äœæããŠãã ããã
// èäœæš© 2023 Google LLC // SPDX-License-Identifier: Apache-2.0 /// Determine the length of the collatz sequence beginning at `n`. fn collatz_length(mut n: i32) -> u32 { todo!("ãããå®è£ ããŠãã ãã") } fn main() { println!("Length: {}", collatz_length(11)); // should be 15 }
è§£ç
// èäœæš© 2023 Google LLC // SPDX-License-Identifier: Apache-2.0 /// Determine the length of the collatz sequence beginning at `n`. fn collatz_length(mut n: i32) -> u32 { let mut len = 1; while n > 1 { n = if n % 2 == 0 { n / 2 } else { 3 * n + 1 }; len += 1; } len } fn main() { println!("Length: {}", collatz_length(11)); // should be 15 }
ãã®è§£çã§ã¯ãããã€ãã®éèŠãª Rust ã®æ©èœã瀺ããŠããŸãã
mutåŒæ°:nåŒæ°ã¯mut nãšããŠå®£èšãããŠããŸããããã«ãããããŒã«ã«å€æ°nã¯é¢æ°ã¹ã³ãŒãå ã§å¯å€ã«ãªããŸããæŽæ°ã¯å€æž¡ããããCopyåã§ãããããããã¯åŒã³åºãå ã®å€ã«ã¯åœ±é¿ããŸãããifåŒ: Rust ã®ifã¯åŒã§ãããå€ãçæããããšãæå³ããŸããif/elseãããã¯ã®çµæãçŽæ¥nã«ä»£å ¥ããŠããŸããããã¯ãååå²ã®äžã§n = ...ãšæžããããç°¡æœã§ãã- æé»ã® return: 颿°ã¯
lenã§çµãã£ãŠããïŒã»ãã³ãã³ãªãïŒããããèªåçã«è¿ãããŸãã
- Collatz æ°åãæå¹ã§ããããã«ã¯ã
nã¯å³å¯ã« 0 ãã倧ãããªããã°ãªããªãããšã«æ³šæããŠãã ããã颿°ã·ã°ããã£ã¯i32ãåãåããŸãããåé¡æã¯æ£ã®æŽæ°ãæ³å®ããŠããŸããããå ç¢ãªå®è£ ã§ã¯u32ã䜿ãããç¡å¹ãªå ¥åïŒ0 ãŸãã¯è² ã®æ°ïŒãåŠçããããã«OptionãŸãã¯Resultãè¿ããããããŸããããããã§ã¯n <= 0ã®å Žåã« panic ãç¡éã«ãŒããèµ·ããå¯èœæ§ããããŸãã - Fibonacci ã®æŒç¿ãšåæ§ã«ã
nã倧ãããªãããããšãªãŒããŒãããŒãæœåšçãªåé¡ã«ãªããŸãã
ãåž°ããªãã
session outline
ã¿ãã«ãšé å
segment outline
- Rust ã§ããªããã£ãåãã©ã®ããã«æ©èœããããèŠãŠããŸãããæ¬¡ã¯ãæ°ãã è€ååã®æ§ç¯ãå§ããçªã§ãã
é å
// Copyright 2024 Google LLC // SPDX-License-Identifier: Apache-2.0 fn main() { let mut a: [i8; 5] = [5, 4, 3, 2, 1]; a[2] = 0; println!("a: {a:?}"); }
-
é åã¯ã
[0; 1024]ã®ãããªççž®æ§æã䜿ã£ãŠåæåããããšãã§ããŸãã ããã¯ããã¹ãŠã®èŠçŽ ãåãå€ã§åæåããããšããã æåã§åæåããã®ã倧å€ãªå€§ããªé åãããå Žåã«äŸ¿å©ã§ãã -
é åå
[T; N]ã®å€ã¯ãåãåTã®èŠçŽ ãNåïŒã³ã³ãã€ã«æå®æ°ïŒ ä¿æããŸããé åã®é·ã㯠åã®äžéš ã§ããããšã«æ³šæããŠãã ãããã€ãŸãã[u8; 3]ãš[u8; 4]㯠2 ã€ã®ç°ãªãåãšèŠãªãããŸãããµã€ãºãå®è¡æã« 決ãŸãã¹ã©ã€ã¹ã«ã€ããŠã¯ãåŸã§æ±ããŸãã -
ç¯å²å€ã®é åèŠçŽ ã«ã¢ã¯ã»ã¹ããŠã¿ãŠãã ãããã³ã³ãã€ã©ã¯ãã®ã€ã³ããã¯ã¹ã å®å šã§ã¯ãªãããšã倿ã§ããããããã®ã³ãŒãã¯ã³ã³ãã€ã«ãããŸãã:
// Copyright 2024 Google LLC // SPDX-License-Identifier: Apache-2.0 fn main() { let mut a: [i8; 5] = [5, 4, 3, 2, 1]; a[6] = 0; println!("a: {a:?}"); }
- é åã¢ã¯ã»ã¹ã¯å®è¡æã«ãã§ãã¯ãããŸããRust ã¯å¯èœãªå Žåããããã® ãã§ãã¯ãæé©åã«ãã£ãŠåãé€ããŸããã€ãŸããã³ã³ãã€ã©ãã¢ã¯ã»ã¹ã®å®å šæ§ã 蚌æã§ãããªããããé«ãæ§èœã®ããã«å®è¡æãã§ãã¯ãåé€ããŸããããã㯠unsafe Rust ã䜿ãããšã§åé¿ã§ããŸãããã®æé©åã¯éåžžã«åªããŠããããã å®è¡æãã§ãã¯ã倱æããäŸã瀺ãã®ã¯ç°¡åã§ã¯ãããŸãããæ¬¡ã®ã³ãŒã㯠ã³ã³ãã€ã«ãããŸãããå®è¡æã« panic ããŸã:
// Copyright 2024 Google LLC // SPDX-License-Identifier: Apache-2.0 fn get_index() -> usize { 6 } fn main() { let mut a: [i8; 5] = [5, 4, 3, 2, 1]; a[get_index()] = 0; println!("a: {a:?}"); }
-
é åã«å€ãä»£å ¥ããããã«ãªãã©ã«ã䜿ããŸãã
-
é åã¯ããŒãã«ç¢ºä¿ãããŸãããé åã¯ã³ã³ãã€ã«æã«åããåºå®ãµã€ãºãæã€ éåžžã®å€ã§ãããã€ãŸãã¹ã¿ãã¯äžã«çœ®ãããŸããããã¯ãé åãããã©ã«ãã§ ããŒãã«ç¢ºä¿ãããããšãããã¬ããŒãžã³ã¬ã¯ã·ã§ã³èšèªã«æ £ããåè¬è ã® æ³å®ãšã¯ç°ãªãå ŽåããããŸãã
-
é åããèŠçŽ ãåé€ããæ¹æ³ããé åã«èŠçŽ ã远å ããæ¹æ³ããããŸããã é åã®é·ãã¯ã³ã³ãã€ã«æã«åºå®ããããããå®è¡æã«ãã®é·ãã倿Žããããšã¯ ã§ããŸããã
ãããã°åºå
-
println!ãã¯ãã¯ã?æžåŒãã©ã¡ãŒã¿ã§ãããã°å®è£ ãèŠæ±ããŸã:{}ã¯ããã©ã«ãåºåãäžãã{:?}ã¯ãããã°åºåãäžããŸããæŽæ°ã æååã®ãããªåã¯ããã©ã«ãåºåãå®è£ ããŠããŸãããé åã¯ãããã°åºåãã å®è£ ããŠããŸãããã€ãŸããããã§ã¯ãããã°åºåã䜿ããªããã°ãªããŸããã -
#ã远å ãããšãããšãã°{a:#?}ã®ããã«ãæŽåœ¢è¡šç€ºã圢åŒã«ãªãã ããèªã¿ããããªãããšããããŸãã
ã¿ãã«
// Copyright 2024 Google LLC // SPDX-License-Identifier: Apache-2.0 fn main() { let t: (i8, bool) = (7, true); dbg!(t.0); dbg!(t.1); }
-
é åãšåæ§ã«ãã¿ãã«ã¯åºå®é·ã§ãã
-
ã¿ãã«ã¯ãç°ãªãåã®å€ã 1 ã€ã®è€ååã«ãŸãšããŸãã
-
ã¿ãã«ã®ãã£ãŒã«ãã«ã¯ãããªãªããšå€ã®ã€ã³ããã¯ã¹ã䜿ã£ãŠã¢ã¯ã»ã¹ã§ããŸãã ããšãã°
t.0ãt.1ã®ããã«ããŸãã -
空ã®ã¿ãã«
()ã¯ããŠãããåããšåŒã°ããä»ã®èšèªã«ãããvoidã«äŒŒãã æ»ãå€ãååšããªãããšã衚ããŸãã -
é åãšã¯ç°ãªããã¿ãã«ã¯
forã«ãŒãã§ã¯äœ¿çšã§ããŸãããããã¯ãforã«ãŒãã§ã¯ãã¹ãŠã®èŠçŽ ãåãåã§ããå¿ èŠããããŸãããã¿ãã«ã§ã¯ããã§ãªã å Žåãããããã§ãã -
ã¿ãã«ã«èŠçŽ ã远å ãããåé€ãããããæ¹æ³ã¯ãããŸãããèŠçŽ æ°ãšãã®å㯠ã³ã³ãã€ã«æã«åºå®ãããŠãããå®è¡æã«å€æŽããããšã¯ã§ããŸããã
é åã®å埩
for æã¯é
åã«å¯Ÿããå埩ããµããŒãããŠããŸãïŒãã ãã¿ãã«ã¯ãµããŒãããŠããŸããïŒã
// Copyright 2023 Google LLC // SPDX-License-Identifier: Apache-2.0 fn main() { let primes = [2, 3, 5, 7, 11, 13, 17, 19]; for prime in primes { for i in 2..prime { assert_ne!(prime % i, 0); } } }
ãã®æ©èœã§ã¯ IntoIterator ãã¬ã€ãã䜿çšããŸãããããã«ã€ããŠã¯ ãŸã æ±ã£ãŠããŸããã
ããã§ assert_ne! ãã¯ããæ°ããç»å ŽããŸããassert_eq! ãã¯ããš assert! ãã¯ãããããŸãããããã¯åžžã«ãã§ãã¯ãããŸãããdebug_assert! ã®ãããªãããã°å°çšã®ããªã¢ã³ãã¯ããªãªãŒã¹ãã«ãã§ã¯äœããªããã®ã«ã³ã³ãã€ã«ãããŸãã
ãã¿ãŒã³ãšåé æçž
Rust ã§ã¯ããã¿ãŒã³ãããã䜿ã£ãŠãã¿ãã«ã®ãããªãã倧ããªå€ããã®æ§æèŠçŽ ã«åè§£ããŠæçžã§ããŸãã
// èäœæš© 2023 Google LLC // SPDX-License-Identifier: Apache-2.0 fn check_order(tuple: (i32, i32, i32)) -> bool { let (left, middle, right) = tuple; left < middle && middle < right } fn main() { let tuple = (1, 5, 3); println!( "{tuple:?}: {}", if check_order(tuple) { "ordered" } else { "unordered" } ); }
- ããã§äœ¿ãããŠãããã¿ãŒã³ã¯ãirrefutableãã§ããã€ãŸããã³ã³ãã€ã©ã¯
=ã®å³èŸºã®å€ããã®ãã¿ãŒã³ãšåãæ§é ãæã€ããšãéçã«æ€èšŒã§ããŸãã - 倿°åã¯ãã©ã®ãããªå€ã«ãåžžã«ããããã irrefutable ãªãã¿ãŒã³ã§ãããã®ããã
letã䜿ã£ãŠåäžã®å€æ°ã宣èšããããšãã§ããŸãã - Rust ã¯æ¡ä»¶åŒã®äžã§ãã¿ãŒã³ã䜿ãããšããµããŒãããŠãããããã«ããç䟡æ¯èŒãšåé æçžãåæã«è¡ããŸãããã®åœ¢åŒã®ãã¿ãŒã³ãããã«ã€ããŠã¯ãåŸã§ãã£ãšè©³ãã説æããŸãã
- äžã®äŸãç·šéããŠããã¿ãŒã³ãããã察象ã®å€ãšäžèŽããªããšãã«ã³ã³ãã€ã© ãšã©ãŒã衚瀺ãããããã«ããŠã¿ãŸãããã
æŒç¿: ãã¹ãããé å
é åã«ã¯ä»ã®é åãå«ããããšãã§ããŸã:
// Copyright 2023 Google LLC // SPDX-License-Identifier: Apache-2.0 let array = [[1, 2, 3], [4, 5, 6], [7, 8, 9]];
ãã®å€æ°ã®åã¯äœã§ããïŒ
äžã®ãããªé
åã䜿ã£ãŠãè¡åã転眮ããïŒè¡ãåã«ããïŒé¢æ° transpose ãæžããŠãã ãã:
以äžã®ã³ãŒãã https://play.rust-lang.org/ ã«ã³ããŒããŠã颿°ãå®è£ ããŠãã ããã ãã®é¢æ°ã¯ 3Ã3 è¡åã«å¯ŸããŠã®ã¿åäœããŸãã
// Copyright 2023 Google LLC // SPDX-License-Identifier: Apache-2.0 fn transpose(matrix: [[i32; 3]; 3]) -> [[i32; 3]; 3] { todo!() } fn main() { let matrix = [ [101, 102, 103], // <-- the comment makes rustfmt add a newline [201, 202, 203], [301, 302, 303], ]; println!("Original:"); for row in matrix { println!("{row:?}"); } let transposed = transpose(matrix); println!("\nTransposed:"); for row in transposed { println!("{row:?}"); } }
è§£ç
// Copyright 2023 Google LLC // SPDX-License-Identifier: Apache-2.0 fn transpose(matrix: [[i32; 3]; 3]) -> [[i32; 3]; 3] { let mut result = [[0; 3]; 3]; for i in 0..3 { for j in 0..3 { result[j][i] = matrix[i][j]; } } result } fn main() { let matrix = [ [101, 102, 103], // <-- the comment makes rustfmt add a newline [201, 202, 203], [301, 302, 303], ]; println!("Original:"); for row in matrix { println!("{row:?}"); } let transposed = transpose(matrix); println!("\nTransposed:"); for row in transposed { println!("{row:?}"); } }
- é
åå: å
[[i32; 3]; 3]ã¯ããµã€ãº 3 ã®é åã衚ãã åèŠçŽ èªäœã 3 åã®i32ãããªãé åã§ããããã¯ã倿¬¡å é åã Rust ã§é垞衚çŸããæ¹æ³ã§ãã - åæå:
resultã¯ãå€ãåããåã«ãŒã ([[0; 3]; 3]) ã§ åæåããŸããRust ã§ã¯ããã¹ãŠã®å€æ°ã¯äœ¿çšåã«åæåãããŠãã å¿ èŠããããå®å šãª Rust ã«ã¯ãæªåæåã¡ã¢ãªããšããæŠå¿µã¯ ãããŸããã - Copy ã»ãã³ãã£ã¯ã¹:
Copyå (i32ãªã©) ã®é åèªäœãCopyã§ããmatrixã颿°ã«æž¡ããšã倿ž¡ãã«ãã£ãŠã³ããŒãããŸãã倿°resultã¯ãæ°ããå¥åã®é åã§ãã - å埩: æšæºçãªç¯å² (
0..3) ã䜿ã£ãforã«ãŒãã§ãæ·»åãå埩 åŠçããŸããRust ã«ã¯åŒ·åãªã€ãã¬ãŒã¿ãããããããã¯åŸã§èŠãŸããã ãã®è¡åã®è»¢çœ®ã§ã¯ã€ã³ããã¯ã¹æå®ãåãããããããæ¹ã§ãã
[i32; 3]ã¯[i32; 4]ãšã¯å¥ã®åã§ããããšã«è§ŠããŠãã ãããé åã®ãµã€ãºã¯ åã·ã°ããã£ã®äžéšã§ãã- åŠçã«ã
matrixã倿ŽããåŸã«ãããçŽæ¥è¿ãããšãããšã©ããªããïŒã·ã°ããã£ãmut matrixã«å€æŽããå ŽåïŒãå°ããŠãã ãããïŒçã: åäœããŸãããè¿ãããã®ã¯ 倿Žããã ã³ã㌠ã§ãããmainå ã®å ã®å€ã¯å€æŽãããŸãããïŒ
ãªãã¡ã¬ã³ã¹
segment outline
å ±æåç §
åç §ã¯ããã®å€ã®æææš©ãååŸããããšãªãå¥ã®å€ã«ã¢ã¯ã»ã¹ããããã®ææ®µã§ããããåçšããšãåŒã°ããŸããå ±æåç §ã¯èªã¿åãå°çšã§ãåç §ãããããŒã¿ã¯å€æŽã§ããŸããã
// Copyright 2023 Google LLC // SPDX-License-Identifier: Apache-2.0 fn main() { let a = 'A'; let b = 'B'; let mut r: &char = &a; dbg!(r); r = &b; dbg!(r); }
å T ãžã®å
񑆇
§ã®å㯠&T ã§ããåç
§å€ã¯ & æŒç®åã§äœæããŸãã* æŒç®åã¯åç
§ããããªãã¡ã¬ã³ã¹ããããã®å€ãåãåºããŸãã
-
Rust ã®åç §ã null ã«ãªãããšã¯æ±ºããŠãªããããnull ãã§ãã¯ã¯äžèŠã§ãã
-
åç §ã¯ããã®åç §å ã®å€ããåçšããããšè¡šçŸãããŸããããã¯ãã€ã³ã¿ã«äžæ £ããªåè¬è ã«ãšã£ãŠæçšãªã¢ãã«ã§ããã³ãŒãã¯åç §ã䜿ã£ãŠå€ã«ã¢ã¯ã»ã¹ã§ããŸããããã®å€ã¯äŸç¶ãšããŠå ã®å€æ°ã«ãææããããŠããŸãããã®ã³ãŒã¹ã§ã¯ã3 æ¥ç®ã«æææš©ã«ã€ããŠããã«è©³ããæ±ããŸãã
-
åç §ã¯ãã€ã³ã¿ãšããŠå®è£ ãããŠãããéèŠãªå©ç¹ã® 1 ã€ã¯ãåç §å ã®ãã®ãããã¯ããã«å°ããã§ããããšã§ããC ã C++ ã«æ £ããåè¬è ã¯ãåç §ããã€ã³ã¿ãšããŠèªèããã§ããããã³ãŒã¹ã®åŸåã§ã¯ãRust ãçãã€ã³ã¿ã®äœ¿çšã«èµ·å ããã¡ã¢ãªå®å šæ§ã®ãã°ãã©ã®ããã«é²ãããæ±ããŸãã
-
&ã«ããæç€ºçãªåç §åãå¿ èŠã§ãããã ããã¡ãœããåŒã³åºãæã¯äŸå€ã§ãRust ãèªåçã«åç §åãšããªãã¡ã¬ã³ã¹ãè¡ããŸãã -
Rust ã¯äžéšã®ç¶æ³ã§èªåããªãã¡ã¬ã³ã¹ãè¡ããŸããç¹ã«ã¡ãœããåŒã³åºãæãããã§ãïŒ
r.is_ascii()ã詊ããŠãã ããïŒãC++ ã®ãããª->æŒç®åã¯äžèŠã§ãã -
ãã®äŸã§ã¯ã
rã¯åä»£å ¥ã§ããããã«å¯å€ã«ãªã£ãŠããŸãïŒr = &bïŒãããã«ãã£ãŠrã¯åæçžãããå¥ã®ãã®ãåç §ããããã«ãªããŸããããã¯ãåç §ãžã®ä»£å ¥ãåç §å ã®å€ã倿Žãã C++ ãšã¯ç°ãªããŸãã -
å ±æåç §ã§ã¯ãããšãåç §å ã®å€ãå¯å€ã§ãã£ãŠãããã®å€ã倿Žããããšã¯ã§ããŸããã
*r = 'X'ã詊ããŠãã ããã -
Rust ã¯ããã¹ãŠã®åç §ã®ã©ã€ãã¿ã€ã ã远跡ããŠãããããååã«é·ãçåããããšãä¿èšŒããŸãããã³ã°ãªã³ã°åç §ã¯ safe Rust ã§ã¯çºçããŸããã
-
æææš©ãæ±ãéã«ãåçšãšãã³ã°ãªã³ã°åç §ã®é²æ¢ã«ã€ããŠããã«è©³ãã説æããŸãã
æä»çåç §
æä»çåç
§ã¯ãå¯å€åç
§ãšãåŒã°ããåç
§å
ã®å€ã倿Žã§ãã åç
§ã§ããå㯠&mut T ã§ãã
// Copyright 2023 Google LLC // SPDX-License-Identifier: Apache-2.0 fn main() { let mut point = (1, 2); let x_coord = &mut point.0; *x_coord = 20; println!("point: {point:?}"); }
èŠç¹:
-
ãæä»çããšã¯ããã®åç §ã ãããã®å€ãžã®ã¢ã¯ã»ã¹ã«äœ¿çšã§ããããšãæå³ããŸããä»ã® åç §ïŒå ±æãŸãã¯æä»çïŒã¯åæã«ååšã§ãããæä»çåç §ãååšããéã¯åç §å ã®å€ã« ã¢ã¯ã»ã¹ããããšãã§ããŸããã
x_coordãæå¹ãªéã«&point.0ãäœæããããpoint.0ã倿ŽãããããŠã¿ãŠãã ããã -
let mut x_coord: &i32ãšlet x_coord: &mut i32ã®éãã«æ³šæããŠãã ãããåè ã¯ç°ãªãå€ã«æçžã§ãã å ±æåç §ã§ãããåŸè ã¯å¯å€ãªå€ãžã®æä»çåç §ã§ãã
ã¹ã©ã€ã¹
ã¹ã©ã€ã¹ã¯ããã倧ããªã³ã¬ã¯ã·ã§ã³ã®äžéšãžã®ãã¥ãŒãæäŸããŸãïŒ
// Copyright 2024 Google LLC // SPDX-License-Identifier: Apache-2.0 fn main() { let a: [i32; 6] = [10, 20, 30, 40, 50, 60]; println!("a: {a:?}"); let s: &[i32] = &a[2..4]; println!("s: {s:?}"); }
- ã¹ã©ã€ã¹ã¯ãåãåºãå ã®åããããŒã¿ãåçšããŸãã
-
ã¹ã©ã€ã¹ã¯
aãåçšããè§æ¬åŒ§å ã§éå§ã€ã³ããã¯ã¹ãšçµäº ã€ã³ããã¯ã¹ãæå®ããŠäœæããŸãã -
ã¹ã©ã€ã¹ãã€ã³ããã¯ã¹ 0 ããå§ãŸãå ŽåãRust ã®ç¯å²æ§æã§ã¯éå§ ã€ã³ããã¯ã¹ãçç¥ã§ããŸããã€ãŸãã
&a[0..a.len()]ãš&a[..a.len()]㯠åäžã§ãã -
çµäºåŽã®ã€ã³ããã¯ã¹ã«ã€ããŠãåæ§ãªã®ã§ã
&a[2..a.len()]ãš&a[2..]㯠åäžã§ãã -
ãããã£ãŠãé åå šäœã®ã¹ã©ã€ã¹ã¯
&a[..]ã䜿ããšç°¡åã«äœæã§ããŸãã -
sã¯i32ã®ã¹ã©ã€ã¹ãžã®åç §ã§ããsã®å (&[i32]) ã«ã¯ããã¯ãé åã®é·ããå«ãŸããŠããªãããšã«æ³šç®ã㊠ãã ãããããã«ããããµã€ãºã®ç°ãªãã¹ã©ã€ã¹ã«å¯ŸããŠèšç®ãè¡ããŸãã -
ã¹ã©ã€ã¹ã¯åžžã«å¥ã®ãªããžã§ã¯ãããåçšããŸãããã®äŸã§ã¯ãå°ãªããšã ã¹ã©ã€ã¹ãååšããŠããéã¯ã
aã âaliveâïŒã¹ã³ãŒãå ã«ããããšïŒã§ ãªããã°ãªããŸããã -
äžåºŠäœæããã¹ã©ã€ã¹ãåŸãããæ¡åŒµãããããšã¯ã§ããŸããïŒ
- ã¹ã©ã€ã¹ã¯åºã«ãªããããã¡ãææããŠããªããããèŠçŽ ã远å ã§ããŸããã
- ã¹ã©ã€ã¹ãåºã«ãªããããã¡ã®ãã倧ããªé åãæãããã«æ¡åŒµããããšã ã§ããŸãããã¹ã©ã€ã¹ã¯åºã«ãªããããã¡ã®é·ãã«é¢ããæ å ±ãæããªã ãããã©ããŸã§å€§ããã§ããããç¥ãããšãã§ããŸããã
- ãã倧ããªã¹ã©ã€ã¹ãå¿ èŠãªå Žåã¯ãå ã®ãããã¡ã«æ»ã£ãŠããããã ãã倧ããªã¹ã©ã€ã¹ãäœæããå¿ èŠããããŸãã
æåå
ããã§ãRust ã«ããã 2 ã€ã®æåååãçè§£ã§ããŸãã
&str㯠UTF-8 ãšã³ã³ãŒãããããã€ãã®ã¹ã©ã€ã¹ã§ããã&[u8]ã«äŒŒãŠããŸããString㯠UTF-8 ãšã³ã³ãŒãããããã€ãã®æææš©ãæã€ãããã¡ã§ãããVec<T>ã«äŒŒãŠããŸãã
// Copyright 2024 Google LLC // SPDX-License-Identifier: Apache-2.0 fn main() { let s1: &str = "World"; println!("s1: {s1}"); let mut s2: String = String::from("Hello "); println!("s2: {s2}"); s2.push_str(s1); println!("s2: {s2}"); let s3: &str = &s2[2..9]; println!("s3: {s3}"); }
-
&strã¯æååã¹ã©ã€ã¹ã衚ããŸããããã¯ãã¡ã¢ãªãããã¯ã«æ ŒçŽããã UTF-8 ãšã³ã³ãŒãæžã¿æååããŒã¿ãžã®äžå€åç §ã§ããæååãªãã©ã«ïŒ"Hello"ïŒ ã¯ãããã°ã©ã ã®ãã€ããªã«æ ŒçŽãããŸãã -
Rust ã®
Stringåã¯ããã€ãã®ãã¯ã¿ãå ãã©ãããŒã§ããVec<T>ãš åæ§ã«ãæææš©ãæã¡ãŸãã -
å€ãã®ã»ãã®åãšåæ§ã«ã
String::from()ã¯æååãªãã©ã«ããæååã äœæããŸããString::new()ã¯æ°ãã空æååãäœæããããã«ã¯push()ã¡ãœãããšpush_str()ã¡ãœããã䜿ã£ãŠæååããŒã¿ã远å ã§ããŸãã -
format!()ãã¯ãã¯ãåçãªå€ããæææš©ãæã€æååãçæãã䟿å©ãªæ¹æ³ã§ããprintln!()ãšåãæžåŒæå®ãåãä»ããŸãã -
&ãšå¿ èŠã«å¿ããç¯å²æå®ã䜿ã£ãŠãStringãã&strã¹ã©ã€ã¹ãåçšã§ããŸãã æåå¢çã«æã£ãŠããªããã€ãç¯å²ãéžæãããšããã®åŒã¯ panic ããŸããcharsã€ãã¬ãŒã¿ã¯æåããšã«å埩ãããããæåå¢çãæ£ããæ±ãããšããããããã¡ããæšå¥šãããŸãã -
C++ ããã°ã©ãåã:
&str㯠C++ ã®std::string_viewã ãšèããŠãã ããã ãã ããåžžã«ã¡ã¢ãªå ã®æå¹ãªæååãæããã®ã§ããRust ã®String㯠C++ ã®std::stringã«å€§ãŸãã«çžåœããŸãïŒäž»ãªéã: UTF-8 ãšã³ã³ãŒãããããã€ããã å«ãããããsmall-string optimization ã¯æ±ºããŠäœ¿çšããŸããïŒã -
ãã€ãæååãªãã©ã«ã䜿ããšã
&[u8]å€ãçŽæ¥äœæã§ããŸãã// Copyright 2024 Google LLC // SPDX-License-Identifier: Apache-2.0 fn main() { println!("{:?}", b"abc"); println!("{:?}", &[97, 98, 99]); } -
raw æååã䜿ããšããšã¹ã±ãŒããç¡å¹ã«ãã
&strå€ãäœæã§ããŸã:r"\n" == "\\n"ãåŒçšç¬Šã®äž¡åŽã«åãæ°ã®#ã䜿ãããšã§ãäºéåŒçšç¬Šãåã蟌ããŸãã// Copyright 2024 Google LLC // SPDX-License-Identifier: Apache-2.0 fn main() { println!(r#"<a href="link.html">link</a>"#); println!("<a href=\"link.html\">link</a>"); }
åç §ã®æå¹æ§
Rust ã§ã¯ãåç
§ãåžžã«å®å
šã«äœ¿çšã§ããããã«ããããã®ãåç
§ã«é¢ãã ããã€ãã®ã«ãŒã«ãé©çšãããŸãããã® 1 ã€ã¯ãåç
§ã¯æ±ºã㊠null ã« ãªããªããšããã«ãŒã«ã§ãããã«ãã null ãã§ãã¯ãªãã§å®å
šã«äœ¿çš ã§ããŸãããã 1 ã€ãããã§èŠãŠããã«ãŒã«ã¯ãåç
§ã®å¯¿åœããåç
§å
ã® ããŒã¿ã®å¯¿åœã è¶
ãã ããšã¯ã§ããªãããšãããã®ã§ãã
// Copyright 2024 Google LLC // SPDX-License-Identifier: Apache-2.0 fn main() { let x_ref = { let x = 10; &x }; dbg!(x_ref); }
-
ãã®ã¹ã©ã€ãã¯ãRust ã®åç §ã«ã¯ä»ã®èšèªãšã¯ç°ãªãã«ãŒã«ãããããã åŠçã«åç §ãåãªããã€ã³ã¿ã§ã¯ãªããã®ãšããŠèããããŸãã
-
Rust ã®åçšã«ãŒã«ã®æ®ãã«ã€ããŠã¯ãRust ã®æææš©ã·ã¹ãã ãæ±ã 3 æ¥ç®ã« èŠãŠãããŸãã
ããã«èª¿ã¹ãã«ã¯
- Rust ã«ããã null 蚱容æ§ã«çžåœãããã®ã¯
Optionåã§ãããããã䜿ããš ä»»æã®åããnull 蚱容ãã«ã§ããŸãïŒåç §/ãã€ã³ã¿ã ãã§ã¯ãããŸããïŒã ãã ãããŸã enum ããã¿ãŒã³ãããã¯å°å ¥ããŠããªãã®ã§ãããã§ã¯ããŸã 詳ããç«ã¡å ¥ããªãããã«ããŠãã ããã
æŒç¿: 幟äœåŠ
ç¹ã [f64;3] ãšããŠè¡šçŸãã3 次å
幟äœåŠã®ããã®ããã€ãã®ãŠãŒãã£ãªãã£é¢æ°ãäœæããŸãã颿°ã·ã°ããã£ã¯èªåã§æ±ºããŠãã ããã
// Copyright 2023 Google LLC // SPDX-License-Identifier: Apache-2.0 // å座æšã®äºä¹ãåèšãããã®å¹³æ¹æ ¹ãåãããšã§ãã¯ãã«ã®å€§ããã // èšç®ããŸããå¹³æ¹æ ¹ã®èšç®ã«ã¯ `sqrt()` ã¡ãœããã䜿çšããŸãã // ããšãã° `v.sqrt()` ã®ããã«ããŸãã fn magnitude(...) -> f64 { todo!() } // ãã¯ãã«ã®å€§ãããèšç®ãããã®å€§ããã§å座æšãå²ãããšã§ãã¯ãã«ã // æ£èŠåããŸãã fn normalize(...) { todo!() } // 以äžã® `main` ã䜿ã£ãŠèªåã®å®è£ ããã¹ãããŠãã ããã fn main() { println!("Magnitude of a unit vector: {}", magnitude(&[0.0, 1.0, 0.0])); let mut v = [1.0, 2.0, 9.0]; println!("Magnitude of {v:?}: {}", magnitude(&v)); normalize(&mut v); println!("Magnitude of {v:?} after normalization: {}", magnitude(&v)); }
è§£ç
// èäœæš© 2023 Google LLC // SPDX-License-Identifier: Apache-2.0 /// Calculate the magnitude of the given vector. fn magnitude(vector: &[f64; 3]) -> f64 { let mut mag_squared = 0.0; for coord in vector { mag_squared += coord * coord; } mag_squared.sqrt() } /// Change the magnitude of the vector to 1.0 without changing its direction. fn normalize(vector: &mut [f64; 3]) { let mag = magnitude(vector); for item in vector { *item /= mag; } } fn main() { println!("Magnitude of a unit vector: {}", magnitude(&[0.0, 1.0, 0.0])); let mut v = [1.0, 2.0, 9.0]; println!("Magnitude of {v:?}: {}", magnitude(&v)); normalize(&mut v); println!("Magnitude of {v:?} after normalization: {}", magnitude(&v)); }
-
normalizeã§ã¯ãåèŠçŽ ã倿Žããããã«*item /= magãå®è¡ã§ããããšã« 泚ç®ããŠãã ãããããã¯ãé åãžã®å¯å€åç §ã䜿ã£ãŠå埩åŠçããŠããããã§ããã ãã®çµæforã«ãŒãã¯åèŠçŽ ãžã®å¯å€åç §ãè¿ããŸãã -
ããã§ã¯ã¹ã©ã€ã¹åç §ãåãããšãå¯èœã§ããããšãã°ã
fn magnitude(vector: &[f64]) -> f64ãããã«ãã颿°ã¯ããæ±çšçã«ãªããŸããã ãã®ä»£ããã«å®è¡æã®é·ããã§ãã¯ã®ã³ã¹ããããããŸãã
ãŠãŒã¶ãŒå®çŸ©å
segment outline
ååä»ããã£ãŒã«ããæã€æ§é äœ
C ã C++ ãšåæ§ã«ãRust ã¯ç¬èªã®æ§é äœããµããŒãããŠããŸã:
// Copyright 2023 Google LLC // SPDX-License-Identifier: Apache-2.0 struct Person { name: String, age: u8, } fn describe(person: &Person) { println!("{} is {} years old", person.name, person.age); } fn main() { let mut peter = Person { name: String::from("Peter"), age: 27, }; describe(&peter); peter.age = 28; describe(&peter); let name = String::from("Avery"); let age = 39; let avery = Person { name, age }; describe(&avery); }
éèŠãªãã€ã³ã:
- æ§é äœã¯ C ã C++ ã®ããã«æ©èœããŸãã
- C++ ãšåæ§ã§ãC ãšã¯ç°ãªããåãå®çŸ©ããããã« typedef ã¯äžèŠã§ãã
- C++ ãšã¯ç°ãªããæ§é äœå士ã«ç¶æ¿ã¯ãããŸããã
- ããã§ãæ§é äœã«ã¯ããã€ãã®çš®é¡ãããããšã説æããã®ãããã§ãããã
- ãŒããµã€ãºæ§é äœïŒäŸ:
struct Foo;ïŒã¯ãããåã«å¯ŸããŠãã¬ã€ããå®è£ ããéã«ãå€èªäœã«æ ŒçŽãããããŒã¿ããªãå Žåã«äœ¿ãããããšããããŸãã - 次ã®ã¹ã©ã€ãã§ã¯ããã£ãŒã«ãåãéèŠã§ãªãå Žåã«äœ¿ãããã¿ãã«æ§é äœã玹ä»ããŸãã
- ãŒããµã€ãºæ§é äœïŒäŸ:
- ãã§ã«é©åãªååã®å€æ°ãããå Žåã¯ãçç¥èšæ³ã䜿ã£ãŠæ§é äœãäœæã§ããŸãã
- æ§é äœã®ãã£ãŒã«ãã¯ããã©ã«ãå€ããµããŒãããŠããŸãããããã©ã«ãå€ã¯
Defaultãã¬ã€ããå®è£ ããããšã§æå®ããŸããããã«ã€ããŠã¯åŸã§æ±ããŸãã
ããã«è©³ãã
-
ããã§ã¯ãæ§é äœæŽæ°æ§æã宿Œã§ããŸã:
// Copyright 2023 Google LLC // SPDX-License-Identifier: Apache-2.0 let jackie = Person { name: String::from("Jackie"), ..avery }; -
ããã«ãããå€ãæ§é äœãã倧éšåã®ãã£ãŒã«ããããã¹ãŠãæç€ºçã«æžãåºããã«ã³ããŒã§ããŸããããã¯åžžã«æåŸã®èŠçŽ ã§ãªããã°ãªããŸããã
-
ããã¯äž»ã«
Defaultãã¬ã€ããšçµã¿åãããŠäœ¿ãããŸããæ§é äœæŽæ°æ§æã«ã€ããŠã¯Defaultãã¬ã€ãã®ã¹ã©ã€ãã§ãã詳ãã説æããã®ã§ãåè¬è ãã質åããªãéããããã§ã¯è§ŠããªããŠãããŸããŸããã
ã¿ãã«æ§é äœ
ãã£ãŒã«ãåãéèŠã§ãªãå Žåã¯ãã¿ãã«æ§é äœã䜿çšã§ããŸã:
// èäœæš© 2023 Google LLC // SPDX-License-Identifier: Apache-2.0 struct Point(i32, i32); fn main() { let p = Point(17, 23); println!("({}, {})", p.0, p.1); }
ããã¯ãåäžãã£ãŒã«ãã®ã©ãããŒïŒnewtype ãšåŒã°ããŸãïŒã«ãã䜿ãããŸã:
// èäœæš© 2023 Google LLC // SPDX-License-Identifier: Apache-2.0 struct PoundsOfForce(f64); struct Newtons(f64); fn compute_thruster_force() -> PoundsOfForce { todo!("Ask a rocket scientist at NASA") } fn set_thruster_force(force: Newtons) { // ... } fn main() { let force = compute_thruster_force(); set_thruster_force(force); }
- newtype ã¯ãããªããã£ãåã®å€ã«è¿œå æ
å ±ãæãããããã®åªããæ¹æ³ã§ãã ããšãã°:
- æ°å€ãç¹å®ã®åäœã§æž¬å®ãããŠãã: äžã®äŸã®
Newtonsã - å€ãäœææã«äœããã®æ€èšŒãééããŠããããã䜿çšã®ãã³ã«åã³ æ€èšŒããå¿
èŠããªããªã:
PhoneNumber(String)ãOddNumber(u32)ã
- æ°å€ãç¹å®ã®åäœã§æž¬å®ãããŠãã: äžã®äŸã®
- newtype ãã¿ãŒã³ã«ã€ããŠã¯ã ãIdiomatic Rustãã¢ãžã¥ãŒã« ã§è©³ããæ±ã£ãŠããŸãã
- newtype ã®åäžãã£ãŒã«ãã«ã¢ã¯ã»ã¹ããŠã
f64ã®å€ãNewtonsåã«å ããæ¹æ³ã宿ŒããŠãã ããã- Rust ã¯äžè¬ã«ãèªåã¢ã³ã©ãããçåœå€ãæŽæ°ãšããŠäœ¿çšããããšã®ãããªã æé»çãªå€æãé¿ããŸãã
- æŒç®åãªãŒããŒããŒãã«ã€ããŠã¯ 2 æ¥ç®ã® (æšæºã©ã€ãã©ãªã®ãã¬ã€ã) ã§èª¬æããŸãã
- Rust ã¯äžè¬ã«ãèªåã¢ã³ã©ãããçåœå€ãæŽæ°ãšããŠäœ¿çšããããšã®ãããªã æé»çãªå€æãé¿ããŸãã
- ã¿ãã«æ§é äœã®ãã£ãŒã«ãã 0 åã®å Žåã
()ã¯çç¥ã§ããŸããçµæã¯ ãŒããµã€ãºåïŒZSTïŒã«ãªãããã®å€ã¯ 1 ã€ã ãã§ãïŒååãã®ãã®ïŒã- ããã¯ãäœããã®æ¯ãèããå®è£
ãããããŒã¿ã¯æããªãåã§ããèŠãããŸã ïŒåžžã« EOF ãè¿ãããšã§ãªãŒããŒãšããŠã®æ¯ãèããå®è£
ãã
NullReaderãæ³åããŠãã ããïŒã
- ããã¯ãäœããã®æ¯ãèããå®è£
ãããããŒã¿ã¯æããªãåã§ããèŠãããŸã ïŒåžžã« EOF ãè¿ãããšã§ãªãŒããŒãšããŠã®æ¯ãèããå®è£
ãã
- ãã®äŸã¯ã Mars Climate Orbiter ã®å€±æãžã®ããããªãèšåã§ãã
åæå
enum ããŒã¯ãŒãã䜿ããšãããã€ãã®ç°ãªã ããªã¢ã³ããæã€åãäœæã§ããŸãã
// Copyright 2023 Google LLC // SPDX-License-Identifier: Apache-2.0 #[derive(Debug)] enum Direction { Left, Right, } #[derive(Debug)] enum PlayerMove { Pass, // åçŽãªããªã¢ã³ã Run(Direction), // ã¿ãã«ããªã¢ã³ã Teleport { x: u32, y: u32 }, // æ§é äœããªã¢ã³ã } fn main() { let dir = Direction::Left; let player_move: PlayerMove = PlayerMove::Run(dir); println!("On this turn: {player_move:?}"); }
ãã€ã³ã:
- åæåã䜿ããšãäžé£ã®å€ã 1 ã€ã®åã®äžã«ãŸãšããããŸãã
Directionã¯ããªã¢ã³ããæã€åã§ããDirectionã®å€ã«ã¯ 2 ã€ãããŸã:Direction::LeftãšDirection::Rightã§ããPlayerMove㯠3 ã€ã®ããªã¢ã³ããæã€åã§ããRust ã¯ãã€ããŒãã«å ããŠã å®è¡æã«PlayerMoveã®å€ã«ã©ã®ããªã¢ã³ããå ¥ã£ãŠããããå€å¥ã§ããããã å€å¥åãæ ŒçŽããŸãã- ããã§ãæ§é äœãšåæåãæ¯èŒããŠã¿ããšããã§ããã:
- ã©ã¡ãã§ãããã£ãŒã«ãã®ãªãåçŽãªåœ¢ïŒãŠãããæ§é äœïŒãã ç°ãªãåã®ãã£ãŒã«ããæã€åœ¢ïŒããªã¢ã³ãã®ãã€ããŒãïŒãæãŠãŸãã
- åæåã®ç°ãªãããªã¢ã³ããå¥ã ã®æ§é äœãšããŠå®è£ ããããšãã§ããŸããã ãã®å Žåããããããã¹ãŠåæåã®äžã§å®çŸ©ããå Žåã®ããã«åãåã«ã¯ãªããŸããã
- Rust ã¯å€å¥åãæ ŒçŽããããã«å¿
èŠæå°éã®é åã䜿ããŸãã
-
å¿ èŠã§ããã°ãå¿ èŠæå°ã®ãµã€ãºã®æŽæ°ãæ ŒçŽããŸã
-
èš±å¯ãããããªã¢ã³ãå€ããã¹ãŠã®ããããã¿ãŒã³ãç¶²çŸ ããŠããªãå Žåã Rust ã¯ç¡å¹ãªããããã¿ãŒã³ã䜿ã£ãŠå€å¥åã笊å·åããŸãïŒããããæé©åãïŒã ããšãã°ã
Option<&u8>ã¯æŽæ°ãžã®ãã€ã³ã¿ããŸãã¯Noneããªã¢ã³ãã衚ãNULLãæ ŒçŽããŸãã -
å¿ èŠã«å¿ããŠå€å¥åãå¶åŸ¡ã§ããŸãïŒããšãã°ãC ãšã®äºææ§ã®ããïŒ:
// Copyright 2023 Google LLC // SPDX-License-Identifier: Apache-2.0 #[repr(u32)] enum Bar { A, // 0 B = 10000, C, // 10001 } fn main() { println!("A: {}", Bar::A as u32); println!("B: {}", Bar::B as u32); println!("C: {}", Bar::C as u32); }reprããªãå Žåã10001 㯠2 ãã€ãã«åãŸããããå€å¥åã®å㯠2 ãã€ãã«ãªããŸãã
-
ããã«åŠã¶
Rust ã«ã¯ãåæåãå æããé åãå°ããããããã«é©çšã§ããæé©åã ããã€ããããŸãã
-
ãã«ãã€ã³ã¿æé©å: äžéšã®åã«ã€ããŠã Rust ã¯
size_of::<T>()ãsize_of::<Option<T>>()ãšçããããšãä¿èšŒããŸããå®éã«ãããåäœã®è¡šçŸãã©ã®ããã«èŠãã å¯èœæ§ããã ãã瀺ãããå Žåã® ã³ãŒãäŸã§ãããã®è¡šçŸã«ã€ããŠã³ã³ãã€ã©ã¯ãããªãä¿èšŒãæäŸããªãããã ããã¯å®å šã« unsafe ã§ãã
// Copyright 2023 Google LLC // SPDX-License-Identifier: Apache-2.0 use std::mem::transmute; macro_rules! dbg_bits { ($e:expr, $bit_type:ty) => { println!("- {}: {:#x}", stringify!($e), transmute::<_, $bit_type>($e)); }; } fn main() { unsafe { println!("bool:"); dbg_bits!(false, u8); dbg_bits!(true, u8); println!("Option<bool>:"); dbg_bits!(None::<bool>, u8); dbg_bits!(Some(false), u8); dbg_bits!(Some(true), u8); println!("Option<Option<bool>>:"); dbg_bits!(Some(Some(false)), u8); dbg_bits!(Some(Some(true)), u8); dbg_bits!(Some(None::<bool>), u8); dbg_bits!(None::<Option<bool>>, u8); println!("Option<&i32>:"); dbg_bits!(None::<&i32>, usize); dbg_bits!(Some(&0i32), usize); } }
åãšã€ãªã¢ã¹
åãšã€ãªã¢ã¹ã¯ãå¥ã®åã«å¯ŸããååãäœæããŸãããã® 2 ã€ã®åã¯äºãã«çœ®ãæããŠäœ¿çšã§ããŸãã
// Copyright 2023 Google LLC // SPDX-License-Identifier: Apache-2.0 enum CarryableConcreteItem { Left, Right, } type Item = CarryableConcreteItem; // åãšã€ãªã¢ã¹ã¯ãé·ããŠè€éãªåã§ãã䟿å©ã§ã: use std::cell::RefCell; use std::sync::{Arc, RwLock}; type PlayerInventory = RwLock<Vec<Arc<RefCell<Item>>>>;
-
newtype ã¯ãå¥åã®åãäœæãããããããããä»£æ¿ææ®µã§ããããšããããããŸãã
type InventoryCount = usizeã§ã¯ãªãstruct InventoryCount(usize)ãåªå ããŠãã ããã -
C ããã°ã©ããŒã«ã¯ãããã¯
typedefã«äŒŒããã®ã ãšãããã§ãããã
const
宿°ã¯ã³ã³ãã€ã«æã«è©äŸ¡ããããã®å€ã¯äœ¿çšããããã¹ãŠã®ç®æã«ã€ã³ã©ã€ã³å±éãããŸã:
// Copyright 2024 Google LLC // SPDX-License-Identifier: Apache-2.0 const DIGEST_SIZE: usize = 3; const FILL_VALUE: u8 = calculate_fill_value(); const fn calculate_fill_value() -> u8 { if DIGEST_SIZE < 10 { 42 } else { 13 } } fn compute_digest(text: &str) -> [u8; DIGEST_SIZE] { let mut digest = [FILL_VALUE; DIGEST_SIZE]; for (idx, &b) in text.as_bytes().iter().enumerate() { digest[idx % DIGEST_SIZE] = digest[idx % DIGEST_SIZE].wrapping_add(b); } digest } fn main() { let digest = compute_digest("Hello"); println!("digest: {digest:?}"); }
const å€ãçæããããã«ã³ã³ãã€ã«æã«åŒã³åºããã®ã¯ãconst ãä»ãã颿°ã ãã§ãããã ããconst 颿°ã¯å®è¡æã«åŒã³åºãããšãã§ããŸãã
constã¯æå³è«çã«ã¯ C++ ã®constexprãšäŒŒãããã«æ¯ãèãããšã«èšåãã
static
éç倿°ã¯ããã°ã©ã ã®å®è¡å šäœãéããŠåç¶ããããã ç§»åããŸãã:
// èäœæš© 2024 Google LLC // SPDX-License-Identifier: Apache-2.0 static BANNER: &str = "Welcome to RustOS 3.14"; fn main() { println!("{BANNER}"); }
Rust RFC Book ã§è¿°ã¹ãããŠããããã«ããããã¯äœ¿çšæã«ã€ã³ã©ã€ã³åãããã å®éã«å¯Ÿå¿ããã¡ã¢ãªäœçœ®ãæã¡ãŸãããã㯠unsafe ã³ãŒããçµã¿èŸŒã¿ã³ãŒãã§æçšã§ããã 倿°ã¯ããã°ã©ã ã®å®è¡å
šäœãéããŠåç¶ããŸããã°ããŒãã«ã¹ã³ãŒãã®å€ã« ãªããžã§ã¯ãåäžæ§ãå¿
èŠãšããçç±ããªãå Žåã¯ãäžè¬ã« const ã 奜ãŸããŸãã
staticã¯ãC++ ã®å¯å€ã°ããŒãã«å€æ°ã«äŒŒãŠããŸããstaticã¯ãªããžã§ã¯ãåäžæ§ãã€ãŸããMutex<T>ã®ãããªå éšå¯å€æ§ãæã€åãå¿ èŠãšãã ã¡ã¢ãªäžã®ã¢ãã¬ã¹ãšç¶æ ãæäŸããŸãã
ããã«è©³ãã
static 倿°ã¯ã©ã®ã¹ã¬ããããã§ãã¢ã¯ã»ã¹ã§ãããããSync ã§ãªããã°ãªããŸããã å
éšå¯å€æ§ã¯ã Mutexãã¢ãããã¯åããŸãã¯ åæ§ã®ä»çµã¿ãéããŠå®çŸã§ããŸãã
ååäœ¿çšæã®åæåããµããŒãããæ¹æ³ãšããŠãstatic ã§ OnceLock ã䜿ãã®ã¯äžè¬çã§ãã OnceCell 㯠Sync ã§ã¯ãªãããããã®æèã§ã¯äœ¿çšã§ããŸããã
ã¹ã¬ããããŒã«ã«ããŒã¿ã¯ããã¯ã std::thread_local ã§äœæã§ããŸãã
æŒç¿: ãšã¬ããŒã¿ãŒã€ãã³ã
ãšã¬ããŒã¿ãŒå¶åŸ¡ã·ã¹ãã å
ã®ã€ãã³ãã衚ãããŒã¿æ§é ãäœæããŸãã ããŸããŸãªã€ãã³ããæ§ç¯ããããã®åãšé¢æ°ã¯ãèªåã§å®çŸ©ããŠãã ããã åã {:?} ã§ãã©ãŒãããã§ããããã«ããããã#[derive(Debug)] ã䜿çšããŠãã ããã
ãã®æŒç¿ã§ã¯ãmain ããšã©ãŒãªãå®è¡ãããããã«ãããŒã¿æ§é ãäœæã㊠å€ãèšå®ããã ãã§ååã§ããã³ãŒã¹ã®æ¬¡ã®ããŒãã§ã¯ããããã®æ§é ãã ããŒã¿ãåãåºãæ¹æ³ãæ±ããŸãã
// èäœæš© 2023 Google LLC // SPDX-License-Identifier: Apache-2.0 #![allow(dead_code)] #[derive(Debug)] /// An event in the elevator system that the controller must react to. enum Event { // TODO: å¿ èŠãªããªã¢ã³ãã远å ãã } /// A direction of travel. #[derive(Debug)] enum Direction { Up, Down, } /// The car has arrived on the given floor. fn car_arrived(floor: i32) -> Event { todo!() } /// The car doors have opened. fn car_door_opened() -> Event { todo!() } /// The car doors have closed. fn car_door_closed() -> Event { todo!() } /// A directional button was pressed in an elevator lobby on the given floor. fn lobby_call_button_pressed(floor: i32, dir: Direction) -> Event { todo!() } /// A floor button was pressed in the elevator car. fn car_floor_button_pressed(floor: i32) -> Event { todo!() } fn main() { println!( "A ground floor passenger has pressed the up button: {:?}", lobby_call_button_pressed(0, Direction::Up) ); println!("The car has arrived on the ground floor: {:?}", car_arrived(0)); println!("The car door opened: {:?}", car_door_opened()); println!( "A passenger has pressed the 3rd floor button: {:?}", car_floor_button_pressed(3) ); println!("The car door closed: {:?}", car_door_closed()); println!("The car has arrived on the 3rd floor: {:?}", car_arrived(3)); }
- åŠçãæŒç¿ã®å
é ã«ãã
#![allow(dead_code)]ã«ã€ããŠè³ªåããå Žåãããã¯Eventåã«å¯ŸããŠè¡ã£ãŠããããšããããã衚瀺ããããšã ããªã®ã§å¿ èŠã§ãã ã³ã³ãã€ã©ããããã³ãŒããæ€æ»ããæ¹æ³ã®çްããªä»æ§ã«ãããã³ãŒãã æªäœ¿çšã ãšå€æãããŠããŸããŸãããã®æŒç¿ã®ç®çã§ã¯ç¡èŠããŠæ§ããŸããã
è§£ç
// Copyright 2023 Google LLC // SPDX-License-Identifier: Apache-2.0 #![allow(dead_code)] #[derive(Debug)] /// An event in the elevator system that the controller must react to. enum Event { /// A button was pressed. ButtonPressed(Button), /// The car has arrived at the given floor. CarArrived(Floor), /// The car's doors have opened. CarDoorOpened, /// The car's doors have closed. CarDoorClosed, } /// A floor is represented as an integer. type Floor = i32; /// A direction of travel. #[derive(Debug)] enum Direction { Up, Down, } /// A user-accessible button. #[derive(Debug)] enum Button { /// A button in the elevator lobby on the given floor. LobbyCall(Direction, Floor), /// A floor button within the car. CarFloor(Floor), } /// The car has arrived on the given floor. fn car_arrived(floor: i32) -> Event { Event::CarArrived(floor) } /// The car doors have opened. fn car_door_opened() -> Event { Event::CarDoorOpened } /// The car doors have closed. fn car_door_closed() -> Event { Event::CarDoorClosed } /// A directional button was pressed in an elevator lobby on the given floor. fn lobby_call_button_pressed(floor: i32, dir: Direction) -> Event { Event::ButtonPressed(Button::LobbyCall(dir, floor)) } /// A floor button was pressed in the elevator car. fn car_floor_button_pressed(floor: i32) -> Event { Event::ButtonPressed(Button::CarFloor(floor)) } fn main() { println!( "A ground floor passenger has pressed the up button: {:?}", lobby_call_button_pressed(0, Direction::Up) ); println!("The car has arrived on the ground floor: {:?}", car_arrived(0)); println!("The car door opened: {:?}", car_door_opened()); println!( "A passenger has pressed the 3rd floor button: {:?}", car_floor_button_pressed(3) ); println!("The car door closed: {:?}", car_door_closed()); println!("The car has arrived on the 3rd floor: {:?}", car_arrived(3)); }
- ããŒã¿ãæã€åæå: Rust ã®
enumããªã¢ã³ãã¯ããŒã¿ãæãŠãŸããCarArrived(Floor)ã¯æŽæ°ãæã¡ãButtonPressed(Button)ã¯ãã¹ããããButtonenumãæã¡ãŸããããã«ãããEventã¯åå®å šãªæ¹æ³ã§è±å¯ãªç¶æ ã®éåã衚çŸã§ããŸãã - åãšã€ãªã¢ã¹:
type Floor = i32ã¯i32ã«æå³çãªååãäžããŸããããã«ããå¯èªæ§ã¯åäžããŸãããã³ã³ãã€ã©ã«ãšã£ãŠFloorã¯äŸç¶ãšããŠåãªãi32ã§ãã #[derive(Debug)]: ãã®å±æ§ã¯ã{:?}ã䜿ã£ãŠåæåãåºåçšã«ãã©ãŒãããããã³ãŒããèªåçæããããã«äœ¿ããŸããããããªããã°ãfmt::Debugãã¬ã€ããæåã§å®è£ ããå¿ èŠããããŸãã- ãã¹ããããåæå:
Buttonenumã¯Event::ButtonPressedã®äžã«ãã¹ããããŠããŸãããã®éå±€æ§é ã¯ãè€éãªãã¡ã€ã³ãã¢ãã«åããããã« Rust ã§ãã䜿ãããŸãã
Event::CarDoorOpenedã¯ããŠãããããªã¢ã³ããïŒããŒã¿ãæããªãïŒã§ããäžæ¹ãEvent::CarArrivedã¯ãã¿ãã«ããªã¢ã³ããã§ããããšã«æ³šæããŠãã ãããButtonãå¥åã®enumã«ããŠããçç±ã«ã€ããŠè°è«ããŠãããã§ããããEventã«LobbyCallButtonPressedãšCarFloorButtonPressedã®ããªã¢ã³ããçŽæ¥æãããããšãã§ããŸããã©ã¡ããæå¹ã§ãããé¢é£ããæŠå¿µïŒãã¿ã³ãªã©ïŒããŸãšããããšã§ãã³ãŒãããããã£ãããããããŸãã
2æ¥ç®ãžãããã
ãããŸã§ã« Rust ã®åºç€ãåŠã³ãŸããã
- åºæ¬å: æŽæ°ãããŒã«å€ãæåãã¿ãã«ãé åã
- å¶åŸ¡ãããŒ:
ifåŒãã«ãŒããmatchåŒã - 颿°: 颿°ã®å®çŸ©æ¹æ³ãšåŒã³åºãæ¹æ³ã
- ãŠãŒã¶ãŒå®çŸ©å:
structãšenumã䜿ã£ãããŒã¿ã®ã¢ããªã³ã°ã - åç
§:
&ãš&mutã«ããåºæ¬çãªåçšã
ããã§ãRust ã§ããããåãæ§ç¯ããåºæ¬çãªããžãã¯ãå®è£ ã§ããããã«ãªããŸããïŒ
ã¹ã±ãžã¥ãŒã«
session outline
ãã¿ãŒã³ ãããã³ã°
segment outline
åé§äžèœãªãã¿ãŒã³
1æ¥ç®ã§ã¯ããã¿ãŒã³ã䜿ã£ãŠè€åå€ã åè§£ ããæ¹æ³ãç°¡åã«èŠãŸãããããã§ãããæ¯ãè¿ãã€ã€ããã¿ãŒã³ã§è¡šçŸã§ããã»ãã®ããã€ãã®ããšã«ã€ããŠèŠãŠãããŸããã:
// Copyright 2025 Google LLC // SPDX-License-Identifier: Apache-2.0 fn takes_tuple(tuple: (char, i32, bool)) { let a = tuple.0; let b = tuple.1; let c = tuple.2; // ããã¯äžãšåãããšãè¡ããŸãã let (a, b, c) = tuple; // æåã®èŠçŽ ã¯ç¡èŠãã2çªç®ãš3çªç®ã ããæçžããŸãã let (_, b, c) = tuple; // æåŸã®èŠçŽ ä»¥å€ããã¹ãŠç¡èŠããŸãã let (.., c) = tuple; } fn main() { takes_tuple(('a', 777, true)); }
-
ããã§ç€ºãããã¿ãŒã³ã¯ãã¹ãŠ åé§äžèœ ã§ãããå³èŸºã®å€ã«åžžã«äžèŽããããšãæå³ããŸãã
-
ãã¿ãŒã³ã¯ãåé§äžèœãªãã¿ãŒã³ãå«ããŠãåã«åºæã§ããã¿ãã«ã«èŠçŽ ã远å ãŸãã¯åé€ããŠãçµæãšããŠçããã³ã³ãã€ã©ãšã©ãŒãèŠãŠã¿ãŠãã ããã
-
倿°åã¯åžžã«äžèŽãããã¿ãŒã³ã§ãããäžèŽããå€ããã®ååã®æ°ãã倿°ã«æçžããŸãã
-
_ã¯åžžã«ä»»æã®å€ã«äžèŽãããã¿ãŒã³ã§ãããäžèŽããå€ã¯ç Žæ£ãããŸãã -
..ã䜿ããšãè€æ°ã®å€ãäžåºŠã«ç¡èŠã§ããŸãã
ããã«è©ŠããŠã¿ã
-
ãŸããã¿ãã«ã®äžå€®ã®èŠçŽ ãç¡èŠãããªã©ã
..ã®ããé«åºŠãªäœ¿ãæ¹ã瀺ãããšãã§ããŸãã#![allow(unused)] fn main() { // Copyright 2025 Google LLC // SPDX-License-Identifier: Apache-2.0 fn takes_tuple(tuple: (char, i32, bool, u8)) { let (first, .., last) = tuple; } } -
ãããã®ãã¿ãŒã³ã¯ã©ããé åã§ãæ©èœããŸã:
#![allow(unused)] fn main() { // Copyright 2025 Google LLC // SPDX-License-Identifier: Apache-2.0 fn takes_array(array: [u8; 5]) { let [first, .., last] = array; } }
å€ã®ãããã³ã°
match ããŒã¯ãŒãã䜿ããšãå€ã 1 ã€ä»¥äžã® ãã¿ãŒã³ ã«ç
§åã§ããŸãããã¿ãŒã³ 㯠C ã C++ ã® switch ãšåæ§ã«åçŽãªå€ã«ãã§ããŸãããããè€éãªæ¡ä»¶ã衚çŸãã ããã«ã䜿ããŸã:
// Copyright 2024 Google LLC // SPDX-License-Identifier: Apache-2.0 #[rustfmt::skip] fn main() { let input = 'x'; match input { 'q' => println!("Quitting"), 'a' | 's' | 'w' | 'd' => println!("Moving around"), '0'..='9' => println!("Number input"), key if key.is_lowercase() => println!("Lowercase: {key}"), _ => println!("Something else"), } }
ãã¿ãŒã³å
ã®å€æ°ïŒãã®äŸã§ã¯ keyïŒã¯ãmatch ã¢ãŒã å
ã§äœ¿çšã§ãã ãã€ã³ãã£ã³ã°ãäœæããŸããããã«ã€ããŠã¯æ¬¡ã®ã¹ã©ã€ãã§ããã«åŠã³ãŸãã
match ã¬ãŒãããããšããã®ã¢ãŒã ã¯æ¡ä»¶ãçã®å Žåã«ã®ã¿ãããããŸããæ¡ä»¶ã åœãªããåŸç¶ã®ã±ãŒã¹ã®ãã§ãã¯ãç¶è¡ãããŸãã
éèŠãªãã€ã³ã:
-
ãã¿ãŒã³ã®äžã§ãããã€ãã®ç¹å®ã®æåãã©ã®ããã«äœ¿ãããŠãããã ææãããšããã§ããã
|ã¯or..ã¯ä»»æã®åæ°ã®èŠçŽ ã«ãããããŸã1..=5ã¯çµç«¯ãå«ãç¯å²ã衚ããŸã_ã¯ã¯ã€ã«ãã«ãŒãã§ã
-
ç¬ç«ããæ§ææ©èœãšããŠã® match ã¬ãŒãã¯ããã¿ãŒã³ã ãã§ã¯è¡šçŸããããªã ããè€éãªèããç°¡æœã«è¡šçŸããããšãã«éèŠãã€å¿ èŠã§ãã
-
match ã¬ãŒãã¯ã
=>ã®åŸã«çœ®ãifåŒãšã¯ç°ãªããŸããifåŒã¯ match ã¢ãŒã ãéžæãããããšã§è©äŸ¡ãããŸãããã®ãããã¯å ã®ifæ¡ä»¶ãæºããããªããŠããå ã®matchåŒã®ã»ãã®ã¢ãŒã ãæ€èšãããããšã¯ãããŸããã æ¬¡ã®äŸã§ã¯ãã¯ã€ã«ãã«ãŒããã¿ãŒã³_ =>ã¯è©ŠãããããšãããããŸããã
// Copyright 2024 Google LLC // SPDX-License-Identifier: Apache-2.0 #[rustfmt::skip] fn main() { let input = 'a'; match input { key if key.is_uppercase() => println!("Uppercase"), key => if input == 'q' { println!("Quitting") }, _ => println!("Bug: this is never printed"), } }
-
ã¬ãŒãã§å®çŸ©ããæ¡ä»¶ã¯ã
|ãå«ããã¿ãŒã³å ã®ãã¹ãŠã®åŒã«é©çšãããŸãã -
æ¢åã®å€æ°ã match ã¢ãŒã å ã§ãã®ãŸãŸäœ¿ã£ãŠæ¡ä»¶ã«ããããšã¯ã§ããªãç¹ã«æ³šæã㊠ãã ããã代ããã«ããã¯å€æ°åãã¿ãŒã³ãšããŠè§£éãããæ¢åã®å€æ°ã ã·ã£ããŒã€ã³ã°ããæ°ãã倿°ãäœãããŸããããšãã°æ¬¡ã®ããã«ãªããŸã:
#![allow(unused)] fn main() { // Copyright 2024 Google LLC // SPDX-License-Identifier: Apache-2.0 let expected = 5; match 123 { expected => println!("Expected value is 5, actual is {expected}"), _ => println!("Value was something else"), } }ããã§ã¯æ°å€ 123 ã«å¯ŸããŠããããããããšããŠãããæåã®ã±ãŒã¹ã§ãã®å€ã 5 ãã©ããã確èªããããšèããŠããŸããçŽ æŽã«èãããšãå€ã 5 ã§ã¯ãªããã æåã®ã±ãŒã¹ã¯ãããããªãã¯ãã§ãããããå®éã«ã¯ãããã¯åžžã«ããããã 倿°ãã¿ãŒã³ãšããŠè§£éããããããæåã®åå²ãåžžã«éžã°ããŸãã 代ããã«å®æ°ã䜿ãã°ãæåŸ ã©ããã«åäœããŸãã
ããã«è©³ãã
-
åè¬è ã«ç޹ä»ã§ãããã¿ãŒã³æ§æã®å¥ã®èŠçŽ ãšããŠããã¿ãŒã³ã®äžéšã倿°ã« æçžãã
@æ§æããããŸããããšãã°æ¬¡ã®ããã«ãªããŸã:#![allow(unused)] fn main() { // Copyright 2024 Google LLC // SPDX-License-Identifier: Apache-2.0 let opt = Some(123); match opt { outer @ Some(inner) => { println!("outer: {outer:?}, inner: {inner}"); } None => {} } }ãã®äŸã§ã¯ã
innerã¯åè§£ã«ãã£ãŠOptionããåãåºããå€ 123 ã æã£ãŠããŸããäžæ¹ãouterã¯Some(inner)åŒå šäœããã£ããã£ããããã å®å šãªOption::Some(123)ãå«ã¿ãŸããããã¯ãã£ãã«äœ¿ãããŸãããããã è€éãªãã¿ãŒã³ã§ã¯åœ¹ã«ç«ã€ããšããããŸãã
æ§é äœ
ã¿ãã«ãšåæ§ã«ãæ§é äœããããã³ã°ã«ãã£ãŠåè§£ã§ããŸãã
// Copyright 2022 Google LLC // SPDX-License-Identifier: Apache-2.0 struct Move { delta: (i32, i32), repeat: u32, } #[rustfmt::skip] fn main() { let m = Move { delta: (10, 0), repeat: 5 }; match m { Move { delta: (0, 0), .. } => println!("Standing still"), Move { delta: (x, 0), repeat } => println!("{repeat} step x: {x}"), Move { delta: (0, y), repeat: 1 } => println!("Single step y: {y}"), _ => println!("Other move"), } }
må ã®ãªãã©ã«å€ã倿ŽããŠãã»ãã®ãã¿ãŒã³ã«ãããããããã«ããŠã¿ãŸããããMovementã«æ°ãããã£ãŒã«ãã远å ããå¿ èŠã«å¿ããŠãã¿ãŒã³ã倿ŽããŠã¿ãŸããããdelta: (x, 0)ããã¹ãããããã¿ãŒã³ã§ããããšã«æ³šç®ããŠãã ããã
ããã«è©ŠããŠã¿ã
match &mã詊ããŠããã£ããã£ã®åã確èªããŠãã ããããã¿ãŒã³æ§æèªäœã¯åããŸãŸã§ããããã£ããã£ã¯å ±æåç §ã«ãªããŸãããã㯠match ergonomics ã§ãããenum ã«å¯Ÿããã¡ãœãããå®è£ ãããšãã®match selfã§ãã圹ç«ã¡ãŸããmatch &mut mã§ãåã广ãèµ·ãããŸãããã®å Žåããã£ããã£ã¯æä»çåç §ã«ãªããŸãã
- ãã£ããã£ãšå®æ°åŒã®éãã¯èŠåãã«ããããšããããŸããæåã®ã¢ãŒã ã®
10ã倿°ã«å€ããŠã¿ããšã埮åŠã«ããŸãåããªãããšãåãããŸãããããconstã«å€ãããšãåã³åãããšã確èªããŠãã ããã
åæå
ã¿ãã«ãšåæ§ã«ãåæåããããã«ãã£ãŠåè§£ã§ããŸãã
ãã¿ãŒã³ã¯ãå€ã®äžéšã«å€æ°ãæçžããããã«ã䜿ããŸããããã¯ã åã®æ§é ã調ã¹ãæ¹æ³ã§ãããŸãã¯åçŽãª enum åããå§ããŸãããã
// èäœæš© 2022 Google LLC // SPDX-License-Identifier: Apache-2.0 enum Result { Ok(i32), Err(String), } fn divide_in_two(n: i32) -> Result { if n % 2 == 0 { Result::Ok(n / 2) } else { Result::Err(format!("cannot divide {n} into two equal parts")) } } fn main() { let n = 100; match divide_in_two(n) { Result::Ok(half) => println!("{n} divided in two is {half}"), Result::Err(msg) => println!("sorry, an error happened: {msg}"), } }
ããã§ã¯ãåã¢ãŒã ã䜿ã£ãŠ Result ã®å€ã åè§£ ããŠããŸããæåã® ã¢ãŒã ã§ã¯ãhalf 㯠Ok ããªã¢ã³ãã®äžã®å€ã«æçžãããŸãã2 çªç®ã®ã¢ãŒã ã§ã¯ã msg ã¯ãšã©ãŒã¡ãã»ãŒãžã«æçžãããŸãã
if/elseåŒã¯åæåãè¿ããŠããããããåŸã§matchã«ãã£ãŠã¢ã³ããã¯ãããŸãã- åæåå®çŸ©ã« 3 ã€ç®ã®ããªã¢ã³ãã远å ããã³ãŒããå®è¡ãããšãã®ãšã©ãŒã衚瀺ããŠã¿ãŸããããã³ãŒããç¶²çŸ çã§ãªããªã£ãŠããç®æãšãã³ã³ãã€ã©ãã©ã®ããã«ãã³ããäžããããšããããææããŠãã ããã
- åæåã®åããªã¢ã³ãå ã®å€ã«ã¢ã¯ã»ã¹ã§ããã®ã¯ããã¿ãŒã³ãããããåŸã ãã§ãã
- ç¶²çŸ çã§ãªãå Žåã«äœãèµ·ãããã瀺ããŠãã ããããã¹ãŠã®ã±ãŒã¹ãåŠçãããŠããããšã確èªããŠããããšãããRust ã³ã³ãã€ã©ã®å©ç¹ã«æ³šç®ããŠãã ããã
- æ§é äœé¢šã®ããªã¢ã³ããåæåå®çŸ©ãš
matchã«è¿œå ããŠããã®æ§æã瀺ããŠãã ããããããæ§é äœã«å¯Ÿããããããšæ§æçã«ã©ã®ããã«äŒŒãŠããããææããŠãã ããã
let ã«ããå¶åŸ¡ãããŒ
Rust ã«ã¯ãä»ã®èšèªãšã¯ç°ãªãå¶åŸ¡ãããŒæ§æãããã€ããããŸããããã㯠ãã¿ãŒã³ãããã³ã°ã«äœ¿çšãããŸãã
if letåŒwhile letåŒlet elseåŒ
if let åŒ
ãã® if let åŒ ã䜿ããšãå€ããã¿ãŒã³ã«äžèŽãããã©ããã«å¿ããŠç°ãªãã³ãŒããå®è¡ã§ããŸã:
// Copyright 2025 Google LLC // SPDX-License-Identifier: Apache-2.0 use std::time::Duration; fn sleep_for(secs: f32) { let result = Duration::try_from_secs_f32(secs); if let Ok(duration) = result { std::thread::sleep(duration); println!("slept for {duration:?}"); } } fn main() { sleep_for(-10.0); sleep_for(0.8); }
matchãšã¯ç°ãªããif letã¯ãã¹ãŠã®åå²ãç¶²çŸ ããå¿ èŠã¯ãããŸããããã®ãããmatchãããç°¡æœã«æžããå ŽåããããŸãã- ããããäœ¿ãæ¹ã¯ã
Optionãæ±ãéã«Someã®å€ãåŠçããããšã§ãã matchãšã¯ç°ãªããif letã¯ãã¿ãŒã³ãããã³ã°ã®ã¬ãŒãç¯ããµããŒãããŠããŸãããelseç¯ãšçµã¿åããããšãåŒãšããŠäœ¿çšã§ããŸãã
while let æ
if let ãšåæ§ã«ã while let ãšããããªã¢ã³ãããããå€ããã¿ãŒã³ã«å¯ŸããŠç¹°ãè¿ããã¹ãããŸãã
// Copyright 2025 Google LLC // SPDX-License-Identifier: Apache-2.0 fn main() { let mut name = String::from("Comprehensive Rust ðŠ"); while let Some(c) = name.pop() { dbg!(c); } // ïŒæååãéé ã«ãããã£ãšå¹ççãªæ¹æ³ã¯ãããŸãïŒïŒ }
ããã§ String::pop ã¯ãæååã空ã«ãªããŸã§ã¯ Some(c) ãè¿ãããã®åŸã¯ None ãè¿ããŸãã while let ã䜿ãããšã§ããã¹ãŠã®èŠçŽ ã«å¯ŸããŠå埩ãç¶ããããŸãã
while letã«ãŒãã¯ãå€ããã¿ãŒã³ã«äžèŽããŠããéãç¶ç¶ããããšãææããŠãã ãããwhile letã«ãŒãã¯ãname.pop()ããã¢ã³ã©ããããå€ããªããªã£ããšãã«breakããifæã䜿ã£ãç¡éã«ãŒããšããŠæžãæããããšãã§ããŸããwhile letã¯ããã®ãããªå Žé¢ã®ããã®ã·ã³ã¿ãã¯ã¹ã·ã¥ã¬ãŒãæäŸããŸãã- ãã®åœ¢åŒã¯ãæ¡ä»¶ãåœã®å Žåã«å€ãæããªãå¯èœæ§ããããããåŒãšããŠã¯äœ¿çšã§ããŸããã
let else æ
ãã¿ãŒã³ã«ããããããŠé¢æ°ããè¿ãäžè¬çãªã±ãŒã¹ã§ã¯ã let else ã䜿ããŸãã ãelseãåŽã¯çºæ£ããªããã°ãªããŸããïŒreturnãbreakããŸã㯠panicãã€ãŸãããããã¯ã®æ«å°ŸãŸã§å°éããŠãã®ãŸãŸæããããšã¯ã§ããŸããïŒã
// èäœæš© 2025 Google LLC // SPDX-License-Identifier: Apache-2.0 fn hex_or_die_trying(maybe_string: Option<String>) -> Result<u32, String> { let s = if let Some(s) = maybe_string { s } else { return Err(String::from("None ãåãåããŸãã")); }; let first_byte_char = if let Some(first) = s.chars().next() { first } else { return Err(String::from("ç©ºã®æååãåãåããŸãã")); }; let digit = if let Some(digit) = first_byte_char.to_digit(16) { digit } else { return Err(String::from("16鲿°ã®æ¡ã§ã¯ãããŸãã")); }; Ok(digit) } fn main() { println!("çµæ: {:?}", hex_or_die_trying(Some(String::from("foo")))); }
#![allow(unused)] fn main() { // èäœæš© 2025 Google LLC // SPDX-License-Identifier: Apache-2.0 fn hex_or_die_trying(maybe_string: Option<String>) -> Result<u32, String> { let Some(s) = maybe_string else { return Err(String::from("None ãåãåããŸãã")); }; let Some(first_byte_char) = s.chars().next() else { return Err(String::from("ç©ºã®æååãåãåããŸãã")); }; let Some(digit) = first_byte_char.to_digit(16) else { return Err(String::from("16鲿°ã®æ¡ã§ã¯ãããŸãã")); }; Ok(digit) } }
ããã«è©³ãã
- ãã®æ©æ return ããŒã¹ã®å¶åŸ¡ãããŒã¯ã
Resultããå€ãåãåºãããšããResultãErrã ã£ãå Žåã«ãšã©ãŒãè¿ã Rust ã®ãšã©ãŒãã³ããªã³ã°ã³ãŒãã§ ããèŠãããŸãã - åŠçãã質åãããã°ãå®éã®ãšã©ãŒãã³ããªã³ã°ã³ãŒãã
?ã§ã©ã®ããã« æžããã瀺ããŸãã
æŒç¿: åŒã®è©äŸ¡
ç®è¡åŒã®ããã®ã·ã³ãã«ãªååž°çè©äŸ¡åšãæžããŠã¿ãŸãããã
å°ããªç®è¡åŒã®äŸãšã㊠10 + 20 ãããããã㯠30 ã«è©äŸ¡ãããŸãããã®åŒã¯æšãšããŠè¡šçŸã§ããŸãã
ãã倧ããè€éãªåŒãšã㊠(10 * 9) + ((3 - 4) * 5) ãããããã㯠85 ã«è©äŸ¡ãããŸããããã¯ããã«å€§ããªæšãšããŠè¡šçŸãããŸãã
ã³ãŒãã§ã¯ããã®æšã 2 ã€ã®åã§è¡šçŸããŸãã
// èäœæš© 2023 Google LLC // SPDX-License-Identifier: Apache-2.0 /// An operation to perform on two subexpressions. #[derive(Debug)] enum Operation { Add, Sub, Mul, Div, } /// An expression, in tree form. #[derive(Debug)] enum Expression { /// An operation on two subexpressions. Op { op: Operation, left: Box<Expression>, right: Box<Expression> }, /// A literal value Value(i64), }
ããã§ã® Box åã¯ã¹ããŒããã€ã³ã¿ã§ãããã³ãŒã¹ã®åŸåã§è©³ããæ±ããŸããåŒã¯ããã¹ãã«ãããšãã Box::new ã§ãããã¯ã¹åãã§ããŸããããã¯ã¹åãããåŒãè©äŸ¡ããã«ã¯ãããªãã¡ã¬ã³ã¹æŒç®å (*) ã䜿ã£ãŠãã¢ã³ããã¯ã¹ãããŸã: eval(*boxed_expr)ã
次ã®ã³ãã³ãã§æ°ãã Cargo ã©ã€ãã©ãªãããžã§ã¯ããäœæããŠãã ããã
cargo new --lib evaluator
以äžã®ã³ãŒãã src/lib.rs ãã¡ã€ã«ã«ã³ããŒïŒããŒã¹ãããŠãã ããã
次㫠eval ã®å®è£
ãå§ããŠãã ãããæçµçãªã©ã€ãã©ãªããã¹ãã«åæ Œããããšã cargo test ã§ç¢ºèªããŠãã ãããtodo!() ã䜿ãããã¹ãã 1 ã€ãã€éããŠãããšããã§ãããã#[ignore] ã䜿ãã°ããã¹ããäžæçã«ã¹ãããããããšãã§ããŸãã
#[test]
#[ignore]
fn test_value() { .. }
// èäœæš© 2023 Google LLC // SPDX-License-Identifier: Apache-2.0 /// An operation to perform on two subexpressions. #[derive(Debug)] enum Operation { Add, Sub, Mul, Div, } /// An expression, in tree form. #[derive(Debug)] enum Expression { /// An operation on two subexpressions. Op { op: Operation, left: Box<Expression>, right: Box<Expression> }, /// A literal value Value(i64), } fn eval(e: Expression) -> i64 { todo!() } #[test] fn test_value() { assert_eq!(eval(Expression::Value(19)), 19); } #[test] fn test_sum() { assert_eq!( eval(Expression::Op { op: Operation::Add, left: Box::new(Expression::Value(10)), right: Box::new(Expression::Value(20)), }), 30 ); } #[test] fn test_recursion() { let term1 = Expression::Op { op: Operation::Mul, left: Box::new(Expression::Value(10)), right: Box::new(Expression::Value(9)), }; let term2 = Expression::Op { op: Operation::Mul, left: Box::new(Expression::Op { op: Operation::Sub, left: Box::new(Expression::Value(3)), right: Box::new(Expression::Value(4)), }), right: Box::new(Expression::Value(5)), }; assert_eq!( eval(Expression::Op { op: Operation::Add, left: Box::new(term1), right: Box::new(term2), }), 85 ); } #[test] fn test_zeros() { assert_eq!( eval(Expression::Op { op: Operation::Add, left: Box::new(Expression::Value(0)), right: Box::new(Expression::Value(0)) }), 0 ); assert_eq!( eval(Expression::Op { op: Operation::Mul, left: Box::new(Expression::Value(0)), right: Box::new(Expression::Value(0)) }), 0 ); assert_eq!( eval(Expression::Op { op: Operation::Sub, left: Box::new(Expression::Value(0)), right: Box::new(Expression::Value(0)) }), 0 ); } #[test] fn test_div() { assert_eq!( eval(Expression::Op { op: Operation::Div, left: Box::new(Expression::Value(10)), right: Box::new(Expression::Value(2)), }), 5 ) }
è§£ç
// Copyright 2023 Google LLC // SPDX-License-Identifier: Apache-2.0 /// An operation to perform on two subexpressions. #[derive(Debug)] enum Operation { Add, Sub, Mul, Div, } /// An expression, in tree form. #[derive(Debug)] enum Expression { /// An operation on two subexpressions. Op { op: Operation, left: Box<Expression>, right: Box<Expression> }, /// A literal value Value(i64), } fn eval(e: Expression) -> i64 { match e { Expression::Op { op, left, right } => { let left = eval(*left); let right = eval(*right); match op { Operation::Add => left + right, Operation::Sub => left - right, Operation::Mul => left * right, Operation::Div => left / right, } } Expression::Value(v) => v, } } #[test] fn test_value() { assert_eq!(eval(Expression::Value(19)), 19); } #[test] fn test_sum() { assert_eq!( eval(Expression::Op { op: Operation::Add, left: Box::new(Expression::Value(10)), right: Box::new(Expression::Value(20)), }), 30 ); } #[test] fn test_recursion() { let term1 = Expression::Op { op: Operation::Mul, left: Box::new(Expression::Value(10)), right: Box::new(Expression::Value(9)), }; let term2 = Expression::Op { op: Operation::Mul, left: Box::new(Expression::Op { op: Operation::Sub, left: Box::new(Expression::Value(3)), right: Box::new(Expression::Value(4)), }), right: Box::new(Expression::Value(5)), }; assert_eq!( eval(Expression::Op { op: Operation::Add, left: Box::new(term1), right: Box::new(term2), }), 85 ); } #[test] fn test_zeros() { assert_eq!( eval(Expression::Op { op: Operation::Add, left: Box::new(Expression::Value(0)), right: Box::new(Expression::Value(0)) }), 0 ); assert_eq!( eval(Expression::Op { op: Operation::Mul, left: Box::new(Expression::Value(0)), right: Box::new(Expression::Value(0)) }), 0 ); assert_eq!( eval(Expression::Op { op: Operation::Sub, left: Box::new(Expression::Value(0)), right: Box::new(Expression::Value(0)) }), 0 ); } #[test] fn test_div() { assert_eq!( eval(Expression::Op { op: Operation::Div, left: Box::new(Expression::Value(10)), right: Box::new(Expression::Value(2)), }), 5 ) }
ã¡ãœãããšãã¬ã€ã
segment outline
ã¡ãœãã
Rust ã§ã¯ãæ°ããåã«é¢æ°ãé¢é£ä»ããããšãã§ããŸãããã㯠impl ãããã¯ã§è¡ããŸã:
// Copyright 2023 Google LLC // SPDX-License-Identifier: Apache-2.0 #[derive(Debug)] struct CarRace { name: String, laps: Vec<i32>, } impl CarRace { // ã¬ã·ãŒããªããéçã¡ãœãã fn new(name: &str) -> Self { Self { name: String::from(name), laps: Vec::new() } } // self ãžã®æä»çãªåçšã«ããèªã¿æžãã¢ã¯ã»ã¹ fn add_lap(&mut self, lap: i32) { self.laps.push(lap); } // self ãžã®å ±æã®èªã¿åãå°çšåçšã¢ã¯ã»ã¹ fn print_laps(&self) { println!("Recorded {} laps for {}:", self.laps.len(), self.name); for (idx, lap) in self.laps.iter().enumerate() { println!("Lap {idx}: {lap} sec"); } } // self ã®æä»çãªæææš©ïŒåŸã§æ±ããŸãïŒ fn finish(self) { let total: i32 = self.laps.iter().sum(); println!("Race {} is finished, total lap time: {}", self.name, total); } } fn main() { let mut race = CarRace::new("Monaco Grand Prix"); race.add_lap(70); race.add_lap(68); race.print_laps(); race.add_lap(71); race.print_laps(); race.finish(); // race.add_lap(42); }
self åŒæ°ã¯ãã¬ã·ãŒãããã€ãŸããã®ã¡ãœãããäœçšãããªããžã§ã¯ãã æå®ããŸãã ã¡ãœããã§ãã䜿ãããã¬ã·ãŒãã«ã¯ãããã€ãã®å
±éãã¿ãŒã³ããããŸã:
&self: å ±æãã€äžå€ã®åç §ã䜿ã£ãŠãåŒã³åºãå ãããªããžã§ã¯ãã åçšããŸãããã®åŸããªããžã§ã¯ãã¯åã³äœ¿çšã§ããŸãã&mut self: äžæã§å¯å€ãªåç §ã䜿ã£ãŠãåŒã³åºãå ãããªããžã§ã¯ãã åçšããŸãããã®åŸããªããžã§ã¯ãã¯åã³äœ¿çšã§ããŸããself: ãªããžã§ã¯ãã®æææš©ãååŸããåŒã³åºãå ããã ãŒãããŸãã ã¡ãœããããã®ãªããžã§ã¯ãã®ææè ã«ãªããŸããæææš©ãæç€ºçã« ç§»è²ãããªãéããã¡ãœããããæ»ããšãã«ãã®ãªããžã§ã¯ãã¯ãããã ïŒã¡ã¢ãªè§£æŸïŒãããŸããå®å šãªæææš©ãæã€ããšã¯ãèªåçã«å¯å€ã§ããããšãæå³ããããã§ã¯ãããŸãããmut self: äžãšåãã§ãããã¡ãœããããªããžã§ã¯ãã倿Žã§ããŸãã- ã¬ã·ãŒããªã: ããã¯æ§é äœäžã®éçã¡ãœããã«ãªããŸããéåžžãæ
£äŸçã«
newãšåŒã°ããã³ã³ã¹ãã©ã¯ã¿ãäœãããã«äœ¿ãããŸãã
éèŠãªãã€ã³ã:
- ã¡ãœããã¯é¢æ°ãšæ¯èŒããŠå°å
¥ãããšçè§£ããããããšããããŸãã
- ã¡ãœããã¯ãåïŒæ§é äœãåæåãªã©ïŒã®ã€ã³ã¹ã¿ã³ã¹ã«å¯ŸããŠåŒã³åºãããæå ã®ãã©ã¡ãŒã¿ã¯
selfãšããŠãã®ã€ã³ã¹ã¿ã³ã¹ã衚ããŸãã - éçºè ã¯ãã¡ãœããã¬ã·ãŒãæ§æãæŽ»çšããããæŽçããããããããã«ã¡ãœãã ãéžã¶ããšããããŸããã¡ãœããã䜿ãããšã§ããã¹ãŠã®å®è£ ã³ãŒããäºæž¬ããã ã 1 ãæã«ãŸãšããŠãããŸãã
- ã¡ãœããã¯ãã¬ã·ãŒããæç€ºçã«æž¡ãããšã§ãé¢é£é¢æ°ã®ããã«åŒã³åºãããšãã§ ããŸããããšãã°
CarRace::add_lap(&mut race, 20)ã®ããã«ãªããŸãã
- ã¡ãœããã¯ãåïŒæ§é äœãåæåãªã©ïŒã®ã€ã³ã¹ã¿ã³ã¹ã«å¯ŸããŠåŒã³åºãããæå ã®ãã©ã¡ãŒã¿ã¯
- ã¡ãœããã¬ã·ãŒãã§ããããŒã¯ãŒã
selfã®äœ¿ãæ¹ãææããŠãã ããã- ããã
self: Selfã®çç¥åœ¢ã§ããããšã瀺ããå Žåã«ãã£ãŠã¯æ§é äœåã䜿ã ãããšã瀺ããŠãã ããã Selfã¯ãã®implãããã¯ãå±ããåã®åãšã€ãªã¢ã¹ã§ããããããã¯å ã®ä» ã®å Žæã§ã䜿ããããšã説æããŠãã ãããselfãä»ã®æ§é äœãšåãããã«äœ¿ããããããèšæ³ã§åã ã®ãã£ãŒã«ããåç §ã§ ããããšã«è§ŠããŠãã ãããfinishã 2 åå®è¡ããŠã¿ãŠã&selfãšselfã®éãã瀺ãã«ã¯è¯ãã¿ã€ã ã³ã°ãããããŸãããselfã®ããªãšãŒã·ã§ã³ã«å ããŠã ç¹å¥ãªã©ãããŒå ãšãã£ãã¬ã·ãŒãåãšããŠèš±å¯ãããç¹å¥ãªã©ãããŒåãããããã®äŸãBox<Self>ã§ãã
- ããã
ãã¬ã€ã
Rust ã§ã¯ããã¬ã€ãã䜿ã£ãŠåãæœè±¡åã§ããŸãããã¬ã€ãã¯ã€ã³ã¿ãŒãã§ãŒã¹ã«äŒŒãŠããŸãã
// Copyright 2023 Google LLC // SPDX-License-Identifier: Apache-2.0 trait Pet { /// ãã®ãããã®çºèšã 1 ã€è¿ããŸãã fn talk(&self) -> String; /// ãã®ãããã«ãããã€ããæååãã¿ãŒããã«ã«åºåããŸãã fn greet(&self); }
-
ãã¬ã€ãã¯ããã®ãã¬ã€ããå®è£ ããããã«åãåããŠããªããã°ãªããªãè€æ°ã®ã¡ãœãããå®çŸ©ããŸãã
-
次ã®ããžã§ããªã¯ã¹ãã»ã¯ã·ã§ã³ã§ã¯ããã¬ã€ããå®è£ ãããã¹ãŠã®åã«å¯ŸããŠãžã§ããªãã¯ãªæ©èœãã©ã®ããã«æ§ç¯ããããèŠãŠãããŸãã
ãã¬ã€ããå®è£ ãã
// Copyright 2024 Google LLC // SPDX-License-Identifier: Apache-2.0 trait Pet { fn talk(&self) -> String; fn greet(&self) { println!("Oh you're a cutie! What's your name? {}", self.talk()); } } struct Dog { name: String, age: i8, } impl Pet for Dog { fn talk(&self) -> String { format!("Woof, my name is {}!", self.name) } } fn main() { let fido = Dog { name: String::from("Fido"), age: 5 }; dbg!(fido.talk()); fido.greet(); }
-
Typeã«å¯ŸããŠTraitãå®è£ ããã«ã¯ãimpl Trait for Type { .. }ãããã¯ã䜿ããŸãã -
Go ã®ã€ã³ã¿ãŒãã§ãŒã¹ãšã¯ç°ãªãã察å¿ããã¡ãœãããããã ãã§ã¯ååã§ã¯ãããŸããã
talk()ã¡ãœãããæã€Catåããã£ãŠããimpl Petãããã¯ã«å ¥ã£ãŠããªãéããèªåçã«Petãæºããããšã«ã¯ãªããŸããã -
ãã¬ã€ãã¯äžéšã®ã¡ãœããã«ããã©ã«ãå®è£ ãæäŸã§ããŸããããã©ã«ã å®è£ ã¯ããã®ãã¬ã€ãã®ãã¹ãŠã®ã¡ãœãããå©çšã§ããŸãããã®å Žåã
greetãæäŸãããŠãããtalkã«äŸåããŠããŸãã -
1 ã€ã®åã«å¯ŸããŠè€æ°ã®
implãããã¯ãæã€ããšãã§ããŸããããã«ã¯ã åºæã®implãããã¯ãšãã¬ã€ãimplãããã¯ã®äž¡æ¹ãå«ãŸããŸãã åæ§ã«ã1 ã€ã®åã«å¯ŸããŠè€æ°ã®ãã¬ã€ããå®è£ ããããšãã§ããŸã ïŒå®éãå€ãã®åã¯ããããã®ãã¬ã€ããå®è£ ããŠããŸãïŒãimplãããã¯ã¯è€æ°ã®ã¢ãžã¥ãŒã«ããã¡ã€ã«ã«ãŸããã£ãŠããŠãããŸããŸããã
ã¹ãŒããŒãã¬ã€ã
ãã¬ã€ãã¯ããããå®è£
ããåã«å¯ŸããŠãã¹ãŒããŒãã¬ã€ã ãšåŒã°ããä»ã®ãã¬ã€ãã®å®è£
ãèŠæ±ã§ããŸããããã§ã¯ãPet ãå®è£
ããä»»æã®å㯠Animal ãå®è£
ããªããã°ãªããŸããã
// Copyright 2024 Google LLC // SPDX-License-Identifier: Apache-2.0 trait Animal { fn leg_count(&self) -> u32; } trait Pet: Animal { fn name(&self) -> String; } struct Dog(String); impl Animal for Dog { fn leg_count(&self) -> u32 { 4 } } impl Pet for Dog { fn name(&self) -> String { self.0.clone() } } fn main() { let puppy = Dog(String::from("Rex")); println!("{} has {} legs", puppy.name(), puppy.leg_count()); }
ããã¯ããã¬ã€ãç¶æ¿ããšåŒã°ããããšããããŸãããåè¬è ã¯ããããªããžã§ã¯ãæåã®ç¶æ¿ã®ããã«æ¯ãèããšæåŸ ãã¹ãã§ã¯ãããŸãããããã¯åã«ããã¬ã€ãã®å®è£ ã«è¿œå ã®èŠä»¶ãæå®ããŠããã ãã§ãã
é¢é£å
é¢é£åã¯ããã¬ã€ãã®å®è£ ã«ãã£ãŠæäŸããããã¬ãŒã¹ãã«ããŒåã§ãã
// èäœæš© 2024 Google LLC // SPDX-License-Identifier: Apache-2.0 #[derive(Debug)] struct Meters(i32); #[derive(Debug)] struct MetersSquared(i32); trait Multiply { type Output; fn multiply(&self, other: &Self) -> Self::Output; } impl Multiply for Meters { type Output = MetersSquared; fn multiply(&self, other: &Self) -> Self::Output { MetersSquared(self.0 * other.0) } } fn main() { println!("{:?}", Meters(10).multiply(&Meters(20))); }
-
é¢é£åã¯ãåºååããšåŒã°ããããšããããŸããéèŠãªç¹ã¯ããã®åãéžã¶ã®ã¯åŒã³åºãåŽã§ã¯ãªãå®è£ åŽã ãšããããšã§ãã
-
æšæºã©ã€ãã©ãªã®å€ãã®ãã¬ã€ãã«ã¯ãç®è¡æŒç®åãã¬ã€ãã
Iteratorãå«ããé¢é£åããããŸãã
å°åº
ãµããŒããããŠãããã¬ã€ãã¯ã次ã®ããã«ããŠã«ã¹ã¿ã åã«èªåå®è£ ã§ããŸãã
// èäœæš© 2023 Google LLC // SPDX-License-Identifier: Apache-2.0 #[derive(Debug, Clone, Default)] struct Player { name: String, strength: u8, hit_points: u8, } fn main() { let p1 = Player::default(); // Default ãã¬ã€ã㯠`default` ã³ã³ã¹ãã©ã¯ã¿ã远å ããŸãã let mut p2 = p1.clone(); // Clone ãã¬ã€ã㯠`clone` ã¡ãœããã远å ããŸãã p2.name = String::from("EldurScrollz"); // Debug ãã¬ã€ã㯠`{:?}` ã䜿ã£ãåºåããµããŒãããŸãã println!("{p1:?} vs. {p2:?}"); }
-
å°åºã¯ãã¯ãã«ãã£ãŠå®è£ ãããŠãããå€ãã®ã¯ã¬ãŒããæçšãªæ©èœã远å ããããã®äŸ¿å©ãª derive ãã¯ããæäŸããŠããŸããããšãã°ã
serdeã¯#[derive(Serialize)]ã䜿ã£ãŠæ§é äœã®ã·ãªã¢ã©ã€ãºå¯Ÿå¿ãå°åºã§ããŸãã -
å°åºã¯éåžžãå€ãã®å Žåã«æ£ããå ±éã®å®åå®è£ ãæã€ãã¬ã€ãã«å¯ŸããŠæäŸãããŸããããšãã°ãæåã®
Cloneå®è£ ãããã¬ã€ããå°åºããå Žåãšæ¯ã¹ãŠã©ãã»ã©åé·ã«ãªãåŸããã瀺ããŸãããã// èäœæš© 2023 Google LLC // SPDX-License-Identifier: Apache-2.0 impl Clone for Player { fn clone(&self) -> Self { Player { name: self.name.clone(), strength: self.strength.clone(), hit_points: self.hit_points.clone(), } } }ãã®å Žåãäžèšã®
.clone()ã®ãã¹ãŠãå¿ èŠãšããããã§ã¯ãããŸããããããã¯æåå®è£ ãäžè¬çã«åŸãå®åçãªãã¿ãŒã³ã瀺ããŠãããåŠçã«deriveã®äœ¿çšãæç¢ºã«äŒããå©ãã«ãªããŸãã
æŒç¿: Logger ãã¬ã€ã
log ã¡ãœãããæã€ãã¬ã€ã Logger ã䜿ã£ãŠãã·ã³ãã«ãªãã®ã³ã°ãŠãŒãã£ãªãã£ãèšèšããŠã¿ãŸããããé²è¡ç¶æ³ããã°ã«åºåããå¯èœæ§ãããã³ãŒãã¯ã&impl Logger ãåãåããããã«ãªããŸãããã¹ãã§ã¯ãããã«ãã£ãŠã¡ãã»ãŒãžããã¹ãã®ãã°ãã¡ã€ã«ã«åºåã§ããŸããäžæ¹ãæ¬çªãã«ãã§ã¯ãã¡ãã»ãŒãžããã°ãµãŒããŒã«éä¿¡ã§ããŸãã
ãã ãã以äžã§äžããããŠãã StderrLogger ã¯ãåé·æ§ã«é¢ä¿ãªããã¹ãŠã®ã¡ãã»ãŒãžããã°ã«åºåããŸããããªãã®èª²é¡ã¯ãæå€§åé·æ§ãè¶
ããã¡ãã»ãŒãžãç¡èŠãã VerbosityFilter åãæžãããšã§ãã
ããã¯äžè¬çãªãã¿ãŒã³ã§ããã€ãŸãããã¬ã€ãå®è£ ãã©ããããæ§é äœãããã®åããã¬ã€ããå®è£ ãããã®éçšã§æ¯ãèãã远å ãããšãããã®ã§ãããGenericsãã»ã°ã¡ã³ãã§ã¯ãã©ãããŒãã©ãã察象ã®åã«å¯ŸããŠãžã§ããªãã¯ã«ããæ¹æ³ãèŠãŠãããŸãã
// Copyright 2023 Google LLC // SPDX-License-Identifier: Apache-2.0 trait Logger { /// Log a message at the given verbosity level. fn log(&self, verbosity: u8, message: &str); } struct StderrLogger; impl Logger for StderrLogger { fn log(&self, verbosity: u8, message: &str) { eprintln!("verbosity={verbosity}: {message}"); } } /// Only log messages up to the given verbosity level. struct VerbosityFilter { max_verbosity: u8, inner: StderrLogger, } // TODO: `VerbosityFilter` ã« `Logger` ãã¬ã€ããå®è£ ããã fn main() { let logger = VerbosityFilter { max_verbosity: 3, inner: StderrLogger }; logger.log(5, "FYI"); logger.log(2, "Uhoh"); }
è§£ç
// Copyright 2023 Google LLC // SPDX-License-Identifier: Apache-2.0 trait Logger { /// Log a message at the given verbosity level. fn log(&self, verbosity: u8, message: &str); } struct StderrLogger; impl Logger for StderrLogger { fn log(&self, verbosity: u8, message: &str) { eprintln!("verbosity={verbosity}: {message}"); } } /// Only log messages up to the given verbosity level. struct VerbosityFilter { max_verbosity: u8, inner: StderrLogger, } impl Logger for VerbosityFilter { fn log(&self, verbosity: u8, message: &str) { if verbosity <= self.max_verbosity { self.inner.log(verbosity, message); } } } fn main() { let logger = VerbosityFilter { max_verbosity: 3, inner: StderrLogger }; logger.log(5, "FYI"); logger.log(2, "Uhoh"); }
ãžã§ããªã¯ã¹
segment outline
ãžã§ããªãã¯é¢æ°
Rust ã¯ãžã§ããªã¯ã¹ããµããŒãããŠãããããã«ããã䜿çšãŸãã¯æ ŒçŽãããåã«å¯ŸããŠã¢ã«ãŽãªãºã ãããŒã¿æ§é ïŒãœãŒããäºåæšãªã©ïŒãæœè±¡åã§ããŸãã
// Copyright 2023 Google LLC // SPDX-License-Identifier: Apache-2.0 fn pick<T>(cond: bool, left: T, right: T) -> T { if cond { left } else { right } } fn main() { println!("picked a number: {:?}", pick(true, 222, 333)); println!("picked a string: {:?}", pick(false, 'L', 'R')); }
-
pickãåçžåããããŒãžã§ã³ã瀺ããšåœ¹ç«ã€ããšããããŸãããžã§ããªãã¯ãªpickã«ã€ããŠèª¬æããå㫠瀺ãã°ããžã§ããªã¯ã¹ãã©ã®ããã«ã³ãŒãã®éè€ãæžããããã瀺ããŸããããžã§ããªã¯ã¹ã«ã€ããŠèª¬æããåŸã«ç€ºãã°ãåçžåãã©ã®ããã«æ©èœãããã瀺ããŸãã#![allow(unused)] fn main() { // Copyright 2023 Google LLC // SPDX-License-Identifier: Apache-2.0 fn pick_i32(cond: bool, left: i32, right: i32) -> i32 { if cond { left } else { right } } fn pick_char(cond: bool, left: char, right: char) -> char { if cond { left } else { right } } } -
Rust ã¯ãåŒæ°ãšæ»ãå€ã®åã«åºã¥ããŠ
Tã®åãæšè«ããŸãã -
ãã®äŸã§ã¯ã
Tã«ã¯ããªããã£ãåã®i32ãšcharã ãã䜿ã£ãŠããŸããã ããã§ã¯ãŠãŒã¶ãŒå®çŸ©åãå«ãä»»æã®åã䜿çšã§ããŸãã// Copyright 2023 Google LLC // SPDX-License-Identifier: Apache-2.0 struct Foo { val: u8, } pick(false, Foo { val: 7 }, Foo { val: 99 }); -
ãã㯠C++ ã®ãã³ãã¬ãŒãã«äŒŒãŠããŸãããRust ã¯ãžã§ããªãã¯é¢æ°ãå³åº§ã«éšåçã«ã³ã³ãã€ã«ããããã ãã®é¢æ°ã¯å¶çŽã«äžèŽãããã¹ãŠã®åã«å¯ŸããŠæå¹ã§ãªããã°ãªããŸãããããšãã°ã
condã false ã®ãšãã«pickãleft + rightãè¿ãããã«å€æŽããŠã¿ãŠãã ãããæŽæ°ã§ã®pickã®ã€ã³ã¹ã¿ã³ã¹åã ãã䜿ããã å Žåã§ããRust ã¯ãããç¡å¹ãšã¿ãªããŸããC++ ãªããããèš±ããŸãã -
ãžã§ããªãã¯ã³ãŒãã¯ãåŒã³åºãç®æã«åºã¥ããŠéãžã§ããªãã¯ãªã³ãŒããžãšå€æãããŸããããã¯ãŒãã³ã¹ãæœè±¡å ã§ããæœè±¡åãªãã§ããŒã¿æ§é ãæã§å®è£ ããå ŽåãšããŸã£ããåãçµæãåŸãããŸãã
ãã¬ã€ãå¢ç
ãžã§ããªã¯ã¹ãæ±ããšãã¯ãåã«äœããã®ãã¬ã€ãã®å®è£ ãèŠæ±ããŠããã®ãã¬ã€ãã®ã¡ãœãããåŒã³åºããããã«ãããããšããããããŸãã
ãã㯠T: Trait ã§æå®ã§ããŸãã
// Copyright 2022 Google LLC // SPDX-License-Identifier: Apache-2.0 fn duplicate<T: Clone>(a: T) -> (T, T) { (a.clone(), a.clone()) } struct NotCloneable; fn main() { let foo = String::from("foo"); let pair = duplicate(foo); println!("{pair:?}"); }
-
NotCloneableãäœæããŠããããduplicateã«æž¡ããŠã¿ãŸãããã -
è€æ°ã®ãã¬ã€ããå¿ èŠãªå Žåã¯ã
+ã§é£çµããŸãã -
whereå¥ã瀺ããŸããããåè¬è ã¯ã³ãŒããèªããšãã«ããã«åºäŒããŸãã// Copyright 2022 Google LLC // SPDX-License-Identifier: Apache-2.0 fn duplicate<T>(a: T) -> (T, T) where T: Clone, { (a.clone(), a.clone()) }- ãã©ã¡ãŒã¿ãå€ãå Žåã颿°ã·ã°ããã£ããã£ãããããããŸãã
- 远å ã®æ©èœãããããã匷åã§ãã
- ãã質åããããã远å ã®æ©èœãšã¯
:ã®å·ŠåŽã®åãOption<T>ã®ããã«ä»»æã«ã§ããããšã ãšèª¬æããŠãã ããã
- ãã質åããããã远å ã®æ©èœãšã¯
-
Rust ã¯ïŒãŸã ïŒç¹æ®åããµããŒãããŠããªãããšã«æ³šæããŠãã ãããããšãã°ãå ã®
duplicateããããšããç¹æ®åããduplicate(a: u32)ã远å ããããšã¯ç¡å¹ã§ãã
ãžã§ããªãã¯ãªããŒã¿å
ãžã§ããªã¯ã¹ã䜿ããšãå ·äœçãªãã£ãŒã«ãåãæœè±¡åã§ããŸããåã® ã»ã°ã¡ã³ãã®æŒç¿ã«æ»ããšã次ã®ããã«ãªããŸã:
// Copyright 2023 Google LLC // SPDX-License-Identifier: Apache-2.0 pub trait Logger { /// æå®ããã詳现床ã¬ãã«ã§ã¡ãã»ãŒãžããã°ã«èšé²ããŸãã fn log(&self, verbosity: u8, message: &str); } struct StderrLogger; impl Logger for StderrLogger { fn log(&self, verbosity: u8, message: &str) { eprintln!("verbosity={verbosity}: {message}"); } } /// æå®ããã詳现床ã¬ãã«ä»¥äžã®ã¡ãã»ãŒãžã ãããã°ã«èšé²ããŸãã struct VerbosityFilter<L> { max_verbosity: u8, inner: L, } impl<L: Logger> Logger for VerbosityFilter<L> { fn log(&self, verbosity: u8, message: &str) { if verbosity <= self.max_verbosity { self.inner.log(verbosity, message); } } } fn main() { let logger = VerbosityFilter { max_verbosity: 3, inner: StderrLogger }; logger.log(5, "FYI"); logger.log(2, "Uhoh"); }
- Q: ãªã
impl<L: Logger> .. VerbosityFilter<L>ã§ã¯Lã 2 åæå®ã㊠ããã®ã§ããïŒ åé·ã§ã¯ãªãã®ã§ããïŒ- ããã¯ããžã§ããªãã¯ãªåã«å¯Ÿãããžã§ããªãã¯ãªå®è£ ãããã¯ã ãã ã§ãããããã¯ç¬ç«ããŠãžã§ããªãã¯ã§ãã
- ããã¯ããããã®ã¡ãœãããä»»æã®
Lã«å¯ŸããŠå®çŸ©ãããããšã æå³ããŸãã impl VerbosityFilter<StderrLogger> { .. }ãšæžãããšãã§ããŸããVerbosityFilterèªäœã¯åŒãç¶ããžã§ããªãã¯ãªã®ã§VerbosityFilter<f64>ã䜿ããŸããããã®ãããã¯å ã®ã¡ãœããã¯VerbosityFilter<StderrLogger>ã«å¯ŸããŠã®ã¿å©çšã§ããŸãã
VerbosityFilteråãã®ãã®ã«ã¯ãã¬ã€ãå¢çãä»ããŠããªãç¹ã«æ³šæã㊠ãã ãããããã«å¢çãä»ããããšãã§ããŸãããäžè¬ã« Rust ã§ã¯ãã¬ã€ã å¢çã¯implãããã¯ã«ã ãä»ããŸãã
ãžã§ããªãã¯ãã¬ã€ã
ãã¬ã€ãããåã颿°ãšåãããã«ãžã§ããªãã¯ã«ã§ããŸãããã¬ã€ãã®ãã©ã¡ãŒã¿ ã«ã¯ãäœ¿çšæã«å
·äœçãªåãäžããããŸããããšãã°ãFrom<T> ãã¬ã€ã㯠å倿ãå®çŸ©ããããã«äœ¿ãããŸãã
#![allow(unused)] fn main() { // Copyright 2024 Google LLC // SPDX-License-Identifier: Apache-2.0 pub trait From<T>: Sized { fn from(value: T) -> Self; } }
// Copyright 2024 Google LLC // SPDX-License-Identifier: Apache-2.0 #[derive(Debug)] struct Foo(String); impl From<u32> for Foo { fn from(from: u32) -> Foo { Foo(format!("Converted from integer: {from}")) } } impl From<bool> for Foo { fn from(from: bool) -> Foo { Foo(format!("Converted from bool: {from}")) } } fn main() { let from_int = Foo::from(123); let from_bool = Foo::from(true); dbg!(from_int); dbg!(from_bool); }
-
Fromãã¬ã€ãã«ã€ããŠã¯ãã®ã³ãŒã¹ã®åŸã§æ±ããŸããããã®stdããã¥ã¡ã³ãã«ããå®çŸ© ã¯åçŽãªã®ã§ãåèã®ããããã«è»¢èŒããŠããŸãã -
ãã¬ã€ãã®å®è£ ã¯ãèãããããã¹ãŠã®åãã©ã¡ãŒã¿ãç¶²çŸ ããå¿ èŠã¯ ãããŸãããããã§ã¯ã
Fooã«å¯ŸããFrom<&str>ã®å®è£ ããªããããFoo::from("hello")ã¯ã³ã³ãã€ã«ã§ããŸããã -
ãžã§ããªãã¯ãã¬ã€ãã¯åããå ¥åããšããŠåãåãäžæ¹ãé¢é£åã¯äžçš®ã® ãåºåãåã§ãããã¬ã€ãã¯ãç°ãªãå ¥ååã«å¯ŸããŠè€æ°ã®å®è£ ãæãŠãŸãã
-
å®éã«ã¯ãRust ã§ã¯ä»»æã®å T ã«å¯ŸããŠãããããããã¬ã€ãå®è£ ã¯æå€§ã§ã 1 ã€ã§ãªããã°ãªããŸãããä»ã®ããã€ãã®èšèªãšã¯ç°ãªããRust ã«ã¯ ãæãå ·äœçããªäžèŽãéžã¶ããã®ãã¥ãŒãªã¹ãã£ãã¯ã¯ãããŸããããã® ãµããŒãã远å ããããã®äœæ¥ãé²ããããŠããããã㯠specialization ãšåŒã°ããŸãã
impl Trait
ãã¬ã€ãå¢çãšåæ§ã«ãimpl Trait æ§æã¯é¢æ°ã®åŒæ°ãæ»ãå€ã§äœ¿çšã§ããŸãã
// èäœæš© 2022 Google LLC // SPDX-License-Identifier: Apache-2.0 // 次ã®ç³è¡£æ§æ: // fn add_42_millions<T: Into<i32>>(x: T) -> i32 { fn add_42_millions(x: impl Into<i32>) -> i32 { x.into() + 42_000_000 } fn pair_of(x: u32) -> impl std::fmt::Debug { (x + 1, x - 1) } fn main() { let many = add_42_millions(42_i8); dbg!(many); let many_more = add_42_millions(10_000_000); dbg!(many_more); let debuggable = pair_of(27); dbg!(debuggable); }
impl Trait ã䜿ããšãååãä»ããããªãåãæ±ããŸããimpl Trait ã®æå³ã¯ã䜿ãããäœçœ®ã«ãã£ãŠå°ãç°ãªããŸãã
-
ãã©ã¡ãŒã¿ã§ã¯ã
impl Traitã¯ãã¬ã€ãå¢çä»ãã®å¿åãžã§ããªãã¯ãã©ã¡ãŒã¿ã®ãããªãã®ã§ãã -
æ»ãå€ã®åã§ã¯ãããã¯ãã®ãã¬ã€ããå®è£ ããäœããã®å ·äœçãªåããååãæããã«æå³ããŸããããã¯ãå ¬é API ã§å ·äœçãªåãå ¬éããããªãå Žåã«äŸ¿å©ã§ãã
æ»ãå€äœçœ®ã§ã¯åæšè«ã¯é£ãããªããŸãã
impl Fooãè¿ã颿°ã¯ããœãŒã¹äžã«ãããæžããªããŠããè¿ãå ·äœçãªåãèªã決å®ããŸããcollect<B>() -> Bã®ããã«ãžã§ããªãã¯ãªåãè¿ã颿°ã¯ãBãæºããä»»æã®åãè¿ãããšãã§ããåŒã³åºãåŽãlet x: Vec<_> = foo.collect()ã®ããã«ããããã¯ã¿ãŒããã£ãã·ã¥foo.collect::<Vec<_>>()ã䜿ã£ãŠããã®ãã¡ã® 1 ã€ãéžã¶å¿ èŠãããå ŽåããããŸãã
debuggable ã®åã¯äœã§ãããããlet debuggable: () = .. ã詊ããŠããšã©ãŒã¡ãã»ãŒãžã«äœã衚瀺ãããã確èªããŠãã ããã
dyn Trait
ãžã§ããªã¯ã¹ã«ããéçãã£ã¹ãããã®ããã«ãã¬ã€ãã䜿ãããšã«å ããŠãRust ã¯ãã¬ã€ããªããžã§ã¯ãã«ããåæ¶å»ãããåçãã£ã¹ãããã®ããã«ãã¬ã€ãã䜿ãããšããµããŒãããŠããŸãã
// Copyright 2024 Google LLC // SPDX-License-Identifier: Apache-2.0 struct Dog { name: String, age: i8, } struct Cat { lives: i8, } trait Pet { fn talk(&self) -> String; } impl Pet for Dog { fn talk(&self) -> String { format!("Woof, my name is {}!", self.name) } } impl Pet for Cat { fn talk(&self) -> String { String::from("Miau!") } } // ãžã§ããªã¯ã¹ãšéçãã£ã¹ãããã䜿çšããã fn generic(pet: &impl Pet) { println!("Hello, who are you? {}", pet.talk()); } // åæ¶å»ãšåçãã£ã¹ãããã䜿çšããã fn dynamic(pet: &dyn Pet) { println!("Hello, who are you? {}", pet.talk()); } fn main() { let cat = Cat { lives: 9 }; let dog = Dog { name: String::from("Fido"), age: 5 }; generic(&cat); generic(&dog); dynamic(&cat); dynamic(&dog); }
-
impl Traitãå«ããžã§ããªã¯ã¹ã¯ããžã§ããªãã¯ãå ·äœåãããããããã®ç°ãªãåããšã«ã颿°ã®ç¹æ®åãããã€ã³ã¹ã¿ã³ã¹ãäœæããããã«åçžåã䜿çšããŸããããã¯ããžã§ããªãã¯é¢æ°ã®å éšãããã¬ã€ãã¡ãœãããåŒã³åºãå Žåã§ããã³ã³ãã€ã©ãå®å šãªåæ å ±ãæã£ãŠããããã®åã«å¯ŸããŠäœ¿ãã¹ããã¬ã€ãå®è£ ã解決ã§ãããããäŸç¶ãšããŠéçãã£ã¹ãããã䜿ãããããšãæå³ããŸãã -
dyn Traitã䜿ãå Žåã¯ã代ããã« ä»®æ³ã¡ãœããããŒãã«ïŒvtableïŒãä»ããåçãã£ã¹ãããã䜿ãããŸããããã¯ãã©ã®åã®Petãæž¡ããããã«é¢ä¿ãªããåäžã®fn dynamicã䜿ãããããšãæå³ããŸãã -
dyn Traitã䜿ãå Žåããã¬ã€ããªããžã§ã¯ãã¯äœããã®éæ¥åç §ã®èåŸã«çœ®ãããŠããå¿ èŠããããŸãããã®å Žåã¯åç §ã§ãããBoxã®ãããªã¹ããŒããã€ã³ã¿åã䜿ãããšãã§ããŸãïŒãã㯠3 æ¥ç®ã«å®æŒããŸãïŒã -
å®è¡æã«ã¯ã
&dyn Petã¯ããã¡ãããã€ã³ã¿ããã€ãŸã 2 ã€ã®ãã€ã³ã¿ã®çµãšããŠè¡šçŸãããŸãã1 ã€ã®ãã€ã³ã¿ã¯Petãå®è£ ããå ·äœçãªãªããžã§ã¯ããæãããã 1 ã€ã¯ãã®åã«å¯Ÿãããã¬ã€ãå®è£ ã® vtable ãæããŸãã&dyn Petã«å¯ŸããŠtalkã¡ãœãããåŒã³åºããšããã³ã³ãã€ã©ã¯ vtable å ã®talkçšé¢æ°ãã€ã³ã¿ã調ã¹ããã®é¢æ°ãåŒã³åºããŸãããã®éããã®é¢æ°ã«ã¯DogãŸãã¯Catãžã®ãã€ã³ã¿ãæž¡ãããŸãããããè¡ãããã«ãã³ã³ãã€ã©ã¯Petã®å ·äœçãªåãç¥ã£ãŠããå¿ èŠã¯ãããŸããã -
dyn Traitã¯ãåæ¶å»ãããŠããããšèŠãªãããŸããããã¯ãå ·äœçãªåãäœã§ãããã«ã€ããŠããã¯ãã³ã³ãã€ã«æã®ç¥èãæããªãããã§ãã
æŒç¿: ãžã§ããªãã¯ãª min
ãã®çãæŒç¿ã§ã¯ãOrd ãã¬ã€ãã䜿ã£ãŠ 2 ã€ã®å€ã®æå°å€ã 決å®ãããžã§ããªãã¯ãª min 颿°ãå®è£
ããŸãã
// Copyright 2023 Google LLC // SPDX-License-Identifier: Apache-2.0 use std::cmp::Ordering; // TODO: ãã¹ãã§äœ¿çšããã `min` 颿°ãå®è£ ããã #[test] fn integers() { assert_eq!(min(0, 10), 0); assert_eq!(min(500, 123), 123); } #[test] fn chars() { assert_eq!(min('a', 'z'), 'a'); assert_eq!(min('7', '1'), '1'); } #[test] fn strings() { assert_eq!(min("hello", "goodbye"), "goodbye"); assert_eq!(min("bat", "armadillo"), "armadillo"); }
è§£ç
// Copyright 2023 Google LLC // SPDX-License-Identifier: Apache-2.0 use std::cmp::Ordering; fn min<T: Ord>(l: T, r: T) -> T { match l.cmp(&r) { Ordering::Less | Ordering::Equal => l, Ordering::Greater => r, } } #[test] fn integers() { assert_eq!(min(0, 10), 0); assert_eq!(min(500, 123), 123); } #[test] fn chars() { assert_eq!(min('a', 'z'), 'a'); assert_eq!(min('7', '1'), '1'); } #[test] fn strings() { assert_eq!(min("hello", "goodbye"), "goodbye"); assert_eq!(min("bat", "armadillo"), "armadillo"); }
ãåž°ããªãã
session outline
ã¯ããŒãžã£
segment outline
ã¯ããŒãžã£ã®æ§æ
ã¯ããŒãžã£ã¯çžŠæ£ã䜿ã£ãŠäœæããŸã: |..| ..ã
// èäœæš© 2025 Google LLC // SPDX-License-Identifier: Apache-2.0 fn main() { // ç°¡æœãªæ§æã§ã¯ãåŒæ°ãšæ»ãå€ã®åãæšè«ã§ããŸã: let double_it = |n| n * 2; dbg!(double_it(50)); // ãããã¯ãåãæå®ããæ¬äœãæ³¢ãã£ãã§å²ãã§å®å šã«æç€ºçã«ã§ããŸã: let add_1f32 = |x: f32| -> f32 { x + 1.0 }; dbg!(add_1f32(50.)); }
-
åŒæ°ã¯
|..|ã®éã«æžããŸããæ¬äœã¯{ .. }ã§å²ããŸããã åäžã®åŒã§ããã°çç¥ã§ããŸãã -
åŒæ°ã®åã¯çç¥å¯èœã§ãçç¥ããå Žåã¯æšè«ãããŸããæ»ãå€ã®åã çç¥å¯èœã§ãããæ¬äœã
{ .. }ã§å²ãå Žåã«ã®ã¿æžããŸãã -
ã©ã¡ãã®äŸããåãªããã¹ããã颿°ãšããŠæžãããšãã§ããŸããããã㯠ã¬ãã·ã«ã«ç°å¢ãã倿°ãäœããã£ããã£ããŠããŸãããæ¬¡ã«ãã£ããã£ã èŠãŠãããŸãã
ããã«è©³ãã
-
颿°ã倿°ã«æ ŒçŽã§ããã®ã¯ã¯ããŒãžã£ã ãã§ã¯ãããŸãããéåžžã®é¢æ°ã 倿°ã«å ¥ããŠãã¯ããŒãžã£ãšåãæ¹æ³ã§åŒã³åºããŸã: playground ã®äŸã
- ãªã³ã¯å ã®äŸã§ã¯ãäœããã£ããã£ããªãã¯ããŒãžã£ã¯éåžžã®é¢æ°ãã€ã³ã¿ã«ã å匷å¶ã§ããããšã瀺ããŠããŸãã
ãã£ããã£
ã¯ããŒãžã£ã¯ãå®çŸ©ãããç°å¢ãã倿°ããã£ããã£ã§ããŸãã
// èäœæš© 2025 Google LLC // SPDX-License-Identifier: Apache-2.0 fn main() { let max_value = 5; let clamp = |v| { if v > max_value { max_value } else { v } }; dbg!(clamp(1)); dbg!(clamp(3)); dbg!(clamp(5)); dbg!(clamp(7)); dbg!(clamp(10)); }
-
ããã©ã«ãã§ã¯ãã¯ããŒãžã£ã¯å€ãåç §ã§ãã£ããã£ããŸããããã§ã¯
max_valueã¯clampã«ãã£ãŠãã£ããã£ãããŠããŸããã衚瀺ã®ããã«mainããåŒãç¶ãå©çšã§ããŸããmax_valueãå¯å€ã«ããŠå€ã倿Žããã¯ã©ã³ããããå€ãããäžåºŠè¡šç€ºããŠã¿ãŠãã ããããªãããã¯ããŸãåããªãã®ã§ããããïŒ -
ã¯ããŒãžã£ãå€ã倿Žããå Žåãããããå¯å€åç §ã§ãã£ããã£ããŸãã
clampã«max_value += 1ã远å ããŠã¿ãŠãã ããã -
moveããŒã¯ãŒãã䜿ããšãåç §ãã代ããã«å€ãã ãŒãããããã¯ããŒãžã£ã«åŒ·å¶ã§ããŸããããã¯ã©ã€ãã¿ã€ã ã®æ±ãã§åœ¹ç«ã€ããšããããŸããããšãã°ãã¯ããŒãžã£ããã£ããã£ããå€ããé·ãçåããªããã°ãªããªãå Žåã§ãïŒã©ã€ãã¿ã€ã ã«ã€ããŠã¯åŸã§è©³ããæ±ããŸãïŒãããã¯
move |v| ..ã®ããã«æžããŸãããã®ããŒã¯ãŒãã远å ããŠãclampãå®çŸ©ããåŸã§ãmainãmax_valueã«åŒãç¶ãã¢ã¯ã»ã¹ã§ããã確èªããŠã¿ãŠãã ããã -
ããã©ã«ãã§ã¯ãã¯ããŒãžã£ã¯å€åŽã®ã¹ã³ãŒãã®å倿°ããå¯èœãªéãæãå¶çŽã®å°ãªãã¢ã¯ã»ã¹æ¹æ³ã§ãã£ããã£ããŸãïŒå¯èœãªãå ±æåç §ãæ¬¡ã«æä»çåç §ãæåŸã«ã ãŒãïŒã
moveããŒã¯ãŒãã¯å€ã«ãããã£ããã£ã匷å¶ããŸãã
ã¯ããŒãžã£ãã¬ã€ã
ã¯ããŒãžã£ãŸãã¯ã©ã ãåŒã®åã«ã¯ååãä»ããããŸãããããããããã㯠ç¹å¥ãª Fnã FnMutãããã³ FnOnce ãã¬ã€ããå®è£
ããŠããŸãã
ç¹å¥ãªå fn(..) -> T ã¯é¢æ°ãã€ã³ã¿ã衚ããŸããããã¯ã颿°ã®ã¢ãã¬ã¹ã ãŸãã¯äœããã£ããã£ããªãã¯ããŒãžã£ã®ããããã§ãã
// èäœæš© 2025 Google LLC // SPDX-License-Identifier: Apache-2.0 fn apply_and_log( func: impl FnOnce(&'static str) -> String, func_name: &'static str, input: &'static str, ) { println!("Calling {func_name}({input}): {}", func(input)) } fn main() { let suffix = "-itis"; let add_suffix = |x| format!("{x}{suffix}"); apply_and_log(&add_suffix, "add_suffix", "senior"); apply_and_log(&add_suffix, "add_suffix", "appendix"); let mut v = Vec::new(); let mut accumulate = |x| { v.push(x); v.join("/") }; apply_and_log(&mut accumulate, "accumulate", "red"); apply_and_log(&mut accumulate, "accumulate", "green"); apply_and_log(&mut accumulate, "accumulate", "blue"); let take_and_reverse = |prefix| { let mut acc = String::from(prefix); acc.push_str(&v.into_iter().rev().collect::<Vec<_>>().join("/")); acc }; apply_and_log(take_and_reverse, "take_and_reverse", "reversed: "); }
FnïŒäŸ: add_suffixïŒã¯ããã£ããã£ããå€ãæ¶è²»ã倿ŽãããŸãããã¯ããŒãžã£ãžã® å
񑆇
§ã ãã§åŒã³åºããããããã®ã¯ããŒãžã£ã¯ç¹°ãè¿ãå®è¡ã§ããåæã« å®è¡ããããšããã§ããŸãã
FnMutïŒäŸ: accumulateïŒã¯ããã£ããã£ããå€ã倿Žããå¯èœæ§ããããŸãã ã¯ããŒãžã£ãªããžã§ã¯ãã«ã¯æä»çåç
§ãéããŠã¢ã¯ã»ã¹ãããããç¹°ãè¿ã åŒã³åºããŸãããåæã«ã¯åŒã³åºããŸããã
FnOnceïŒäŸ: take_and_reverseïŒãæã£ãŠããå ŽåããããåŒã³åºããã®ã¯ 1 åã ãã§ãã ãããããšãã¯ããŒãžã£ãšãmove ã«ãã£ãŠãã£ããã£ãããããããå€ãæ¶è²»ãããŸãã
FnMut 㯠FnOnce ã®ãµãã¿ã€ãã§ããFn 㯠FnMut ãš FnOnce ã®ãµãã¿ã€ãã§ãã ã€ãŸããFnOnce ãèŠæ±ãããå Žæã§ããã°ã©ãã§ã FnMut ã䜿ããFnMut ãŸã㯠FnOnce ãèŠæ±ãããå Žæã§ããã°ã©ãã§ã Fn ã䜿ããŸãã
ã¯ããŒãžã£ãåãåã颿°ãå®çŸ©ããéã¯ãå¯èœã§ããã° FnOnceïŒã€ãŸã 1 å åŒã³åºãå ŽåïŒãåãåããããã§ãªããã° FnMutãæåŸã« Fn ãåãåãããã« ãã¹ãã§ããããã«ãããåŒã³åºãåŽã«æå€§ã®æè»æ§ãäžããããŸãã
ããã«å¯ŸããŠãæå
ã«ããã¯ããŒãžã£ã«ã€ããŠæãæè»ãªã®ã¯ Fn ïŒ3 çš®é¡ã®ã¯ããŒãžã£ãã¬ã€ãã®ããããåãåãåŽã«ãæž¡ããŸãïŒã§ã次ã FnMutãæåŸã FnOnce ã§ãã
ã³ã³ãã€ã©ã¯ãã¯ããŒãžã£ãäœããã£ããã£ãããã«å¿ããŠãCopy ïŒäŸ: add_suffixïŒã CloneïŒäŸ: take_and_reverseïŒãæšè«ããŸãã 颿°ãã€ã³ã¿ïŒfn é
ç®ãžã®åç
§ïŒã¯ Copy ãš Fn ãå®è£
ããŸãã
æŒç¿: ãã°ãã£ã«ã¿ãŒ
ä»æäœæãããžã§ããªãã¯ãªãã¬ãŒãããŒã¹ã«ãã¯ããŒãžã£ã䜿ã£ãŠãã°ã¡ãã»ãŒãžããã£ã«ã¿ãªã³ã°ãã Filter ãå®è£
ããŠãã ããããã£ã«ã¿ãªã³ã°è¿°èªãééãããã®ã¯ãå
éšã®ãã¬ãŒã«éä¿¡ããŸãã
// Copyright 2025 Google LLC // SPDX-License-Identifier: Apache-2.0 pub trait Logger { /// Log a message at the given verbosity level. fn log(&self, verbosity: u8, message: &str); } struct StderrLogger; impl Logger for StderrLogger { fn log(&self, verbosity: u8, message: &str) { eprintln!("verbosity={verbosity}: {message}"); } } // TODO: `Filter` ãå®çŸ©ããŠå®è£ ããã fn main() { let logger = Filter::new(StderrLogger, |_verbosity, msg| msg.contains("yikes")); logger.log(5, "FYI"); logger.log(1, "yikes, something went wrong"); logger.log(2, "uhoh"); }
è§£ç
// Copyright 2025 Google LLC // SPDX-License-Identifier: Apache-2.0 pub trait Logger { /// Log a message at the given verbosity level. fn log(&self, verbosity: u8, message: &str); } struct StderrLogger; impl Logger for StderrLogger { fn log(&self, verbosity: u8, message: &str) { eprintln!("verbosity={verbosity}: {message}"); } } /// Only log messages matching a filtering predicate. struct Filter<L, P> { inner: L, predicate: P, } impl<L, P> Filter<L, P> where L: Logger, P: Fn(u8, &str) -> bool, { fn new(inner: L, predicate: P) -> Self { Self { inner, predicate } } } impl<L, P> Logger for Filter<L, P> where L: Logger, P: Fn(u8, &str) -> bool, { fn log(&self, verbosity: u8, message: &str) { if (self.predicate)(verbosity, message) { self.inner.log(verbosity, message); } } } fn main() { let logger = Filter::new(StderrLogger, |_verbosity, msg| msg.contains("yikes")); logger.log(5, "FYI"); logger.log(1, "yikes, something went wrong"); logger.log(2, "uhoh"); }
- ã¯ããŒãžã£ã®æ ŒçŽ: ã¯ããŒãžã£ãæ§é äœã«æ ŒçŽããã«ã¯ããžã§ããªãã¯å ãã©ã¡ãŒã¿ïŒããã§ã¯
PïŒã䜿ããŸããããã¯ãRust ã®åã¯ããŒãžã£ã ã³ã³ãã€ã©ã«ãã£ãŠçæãããäžæã®ç¡ååãæã€ããã§ãã Fnãã¬ã€ãå¢ç: å¢çP: Fn(u8, &str) -> boolã¯ãPã æå®ãããåŒæ°ãšæ»ãå€ã®åã§é¢æ°ãšããŠåŒã³åºããããšãã³ã³ãã€ã©ã« äŒããŸããlogã¯&selfãåãåããããpredicate ã«ã¯äžå€ã«ãã ã¢ã¯ã»ã¹ã§ããªãã®ã§ãFnïŒFnMutãFnOnceã§ã¯ãªãïŒã䜿ããŸãã- ãã£ãŒã«ãã®åŒã³åºã:
(self.predicate)(...)ã䜿ã£ãŠã¯ããŒãžã£ã åŒã³åºããŸããself.predicateãå²ãæ¬åŒ§ã¯ãpredicateãšããååã® ã¡ãœããåŒã³åºããšãã£ãŒã«ãèªäœã®åŒã³åºããåºå¥ããããã«å¿ èŠã§ãã
Fnãå¿ èŠãªçç±ã説æããŸããããFnMutã䜿ããšãlogã¯&mut selfãåãåãå¿ èŠããããããã¯Loggerãã¬ã€ãã® ã·ã°ããã£ãšè¡çªããŸããFnOnceã䜿ããšã1 ä»¶ã®ã¡ãã»ãŒãžãã ãã°ã«èšé²ã§ããŸããïŒnewã®implãããã¯ã«ããã¬ã€ãå¢çãå«ãŸããŠããŸããæè¡çã«ã¯ã ããã¯æ§é äœå®çŸ©ãã®ãã®ã«ã¯å³å¯ã«ã¯å¿ é ã§ã¯ãããŸããïŒãã¬ã€ãå¢çã¯ã ãããã䜿çšããimplãããã¯ã«ã®ã¿çœ®ãããšãã§ããŸãïŒããnewã« ä»ããŠãããšåæšè«ã«åœ¹ç«ã¡ãŸãã
æšæºã©ã€ãã©ãªã®å
segment outline
ãã®ã»ã¯ã·ã§ã³ã®åã¹ã©ã€ãã«ã€ããŠãããã¥ã¡ã³ãããŒãžã確èªããæéãåãã ããäžè¬çãªã¡ãœããã®ããã€ãã匷調ããŠãã ããã
æšæºã©ã€ãã©ãª
Rust ã«ã¯æšæºã©ã€ãã©ãªãä»å±ããŠãããRust ã®ã©ã€ãã©ãªãããã°ã©ã ã§äœ¿ãããå
±éã®åã®éåã確ç«ããã®ã«åœ¹ç«ã¡ãŸããããã«ããã2 ã€ã®ã©ã€ãã©ãªã¯äž¡æ¹ãšãåã String åã䜿ããããåæ»ã«é£æºã§ããŸãã
å®éãRust ã®æšæºã©ã€ãã©ãªã«ã¯ coreãallocãstd ãšããè€æ°ã®å±€ããããŸãã
coreã«ã¯ãlibcãã¢ãã±ãŒã¿ãããã«ã¯ãªãã¬ãŒãã£ã³ã°ã·ã¹ãã ã®ååšã«ãäŸåããªããæãåºæ¬çãªåãšé¢æ°ãå«ãŸããŸããallocã«ã¯ãVecãBoxãArcãªã©ãã°ããŒãã«ãªããŒãã¢ãã±ãŒã¿ãå¿ èŠãšããåãå«ãŸããŸãã- çµã¿èŸŒã¿ Rust ã¢ããªã±ãŒã·ã§ã³ã¯éåžž
coreã®ã¿ã䜿çšãããšãã«ã¯allocã䜿çšããŸãã
ããã¥ã¡ã³ã
Rust ã«ã¯è±å¯ãªããã¥ã¡ã³ãããããŸããããšãã°æ¬¡ã®ãããªãã®ã§ãã
- ã«ãŒã ã«é¢ãããã¹ãŠã®è©³çްã
u8ã®ãããªããªããã£ãåãOptionãBinaryHeapã®ãããªæšæºã©ã€ãã©ãªã®åã
ããã¥ã¡ã³ãã衚瀺ããã«ã¯ãrustup doc --std ãŸã㯠https://std.rs ã䜿çšããŸãã
å®éã®ãšãããèªåã®ã³ãŒãã«ãããã¥ã¡ã³ããä»ããããšãã§ããŸãã
// èäœæš© 2023 Google LLC // SPDX-License-Identifier: Apache-2.0 /// 第1åŒæ°ã第2åŒæ°ã§å²ãåãããã©ãããå€å®ããŸãã /// /// 第2åŒæ°ã 0 ã®å Žåãçµæã¯ false ã§ãã fn is_divisible_by(lhs: u32, rhs: u32) -> bool { if rhs == 0 { return false; } lhs % rhs == 0 }
å
容㯠Markdown ãšããŠæ±ãããŸããå
¬éãããŠãããã¹ãŠã® Rust ã©ã€ãã©ãª crate ã¯ã rustdoc ããŒã«ã䜿ã£ãŠ docs.rs ã§èªåçã«ããã¥ã¡ã³ãåãããŸãããããããã¿ãŒã³ã䜿ã£ãŠ API ã®ãã¹ãŠã® public ãªèŠçŽ ãããã¥ã¡ã³ãåããã®ã Rust ãããæžãæ¹ã§ãã
èŠçŽ ã®å
åŽïŒããšãã°ã¢ãžã¥ãŒã«ã®å
åŽïŒããèŠçŽ ãããã¥ã¡ã³ãåããã«ã¯ã//! ãŸã㯠/*! .. */ ã䜿ããŸãããããã¯ãå
éšããã¥ã¡ã³ãã³ã¡ã³ãããšåŒã°ããŸãã
// èäœæš© 2023 Google LLC // SPDX-License-Identifier: Apache-2.0 //! ãã®ã¢ãžã¥ãŒã«ã«ã¯ãæŽæ°ã®å²ãåãã«é¢ããæ©èœãå«ãŸããŠããŸãã
randcrate ã®çæãããããã¥ã¡ã³ãã https://docs.rs/rand ã§åŠçã«èŠããŠãã ããã
Option
ãã§ã« Option<T> ã®äœ¿çšäŸãããã€ãèŠãŠããŸãããããã¯ãå T ã®å€ããŸãã¯äœããªãç¶æ
ã®ãããããä¿æããŸããããšãã°ã String::find 㯠Option<usize> ãè¿ããŸãã
// Copyright 2023 Google LLC // SPDX-License-Identifier: Apache-2.0 fn main() { let name = "Löwe èè Léopard Gepardi"; let mut position: Option<usize> = name.find('é'); dbg!(position); assert_eq!(position.unwrap(), 14); position = name.find('Z'); dbg!(position); assert_eq!(position.expect("Character not found"), 0); }
-
Optionã¯æšæºã©ã€ãã©ãªã ãã§ãªããåºã䜿ãããŠããŸãã -
unwrapã¯Optionå ã®å€ãè¿ããå€ããªããã° panic ããŸããexpectãåæ§ ã§ããããšã©ãŒã¡ãã»ãŒãžãåãåããŸãã- None ã®ãšãã« panic ããããšã¯ã§ããŸãããNone ã®ãã§ãã¯ã ããã£ãããå¿ããããšã¯ãããŸããã
- äœããææ©ãçµã¿ç«ãŠãŠãããšãã«ã¯ããã¡ãã¡ã§
unwrap/expectã䜿ã ããšããããããŸãããæ¬çªã³ãŒãã§ã¯éåžžãNoneããã£ãšé©åã«æ±ããŸãã
-
ãniche optimizationããšã¯ã
Option<T>ã¯ãTãšããŠæå¹ã§ãªã衚çŸã äœã 1 ã€ã§ãããå Žåãéåžžã¡ã¢ãªäžã§Tãšåããµã€ãºã«ãªãããšããããšã§ãã ããšãã°ãåç §ã¯ NULL ã«ã¯ãªããªãã®ã§ãOption<&T>ã¯èªåçã« NULL ãNoneããªã¢ã³ãã®è¡šçŸãšããŠäœ¿ãããã®çµæ&Tãšåã ã¡ã¢ãªã«æ ŒçŽã§ããŸãã
Result
Result 㯠Option ã«äŒŒãŠããŸãããæäœã®æåãŸãã¯å€±æãããããã ç°ãªã enum ããªã¢ã³ãã§è¡šããŸããããã¯ãžã§ããªãã¯ã§ãResult<T, E> ã®åœ¢ãåããT 㯠Ok ããªã¢ã³ãã§äœ¿ãããE 㯠Err ããªã¢ã³ãã«çŸããŸãã
// Copyright 2023 Google LLC // SPDX-License-Identifier: Apache-2.0 use std::fs::File; use std::io::Read; fn main() { let file: Result<File, std::io::Error> = File::open("diary.txt"); match file { Ok(mut file) => { let mut contents = String::new(); if let Ok(bytes) = file.read_to_string(&mut contents) { println!("Dear diary: {contents} ({bytes} bytes)"); } else { println!("Could not read file content"); } } Err(err) => { println!("The diary could not be opened: {err}"); } } }
Optionãšåæ§ã«ãæåããå€ã¯Resultã®äžã«å ¥ã£ãŠããããã éçºè ã¯ãããæç€ºçã«åãåºãå¿ èŠããããŸããããã¯ãšã©ãŒãã§ãã¯ã ä¿ããŸãããšã©ãŒã決ããŠçºçããªãã¯ãã®å Žåã¯ãunwrap()ãexpect()ã åŒã³åºãããšãã§ãããããéçºè ã®æå³ã瀺ãã·ã°ãã«ã«ãªããŸããResultã®ããã¥ã¡ã³ãã¯äžèªãå§ããŸããè¬çŸ©äžã«èªããã®ã§ã¯ãããŸãããã èšåãã䟡å€ã¯ãããŸãã颿°åã¹ã¿ã€ã«ã®ããã°ã©ãã³ã°ã«åœ¹ç«ã€äŸ¿å©ãª ã¡ãœããã颿°ãæ°å€ãå«ãŸããŠããŸãã- 4æ¥ç®ã§èŠãããã«ã
Resultã¯ãšã©ãŒãã³ããªã³ã°ãå®è£ ããããã® æšæºçãªåã§ãã
String
String ã¯ãæ¡åŒµå¯èœãª UTF-8 ãšã³ã³ãŒãæååã§ã:
// Copyright 2023 Google LLC // SPDX-License-Identifier: Apache-2.0 fn main() { let mut s1 = String::new(); s1.push_str("Hello"); println!("s1: len = {}, capacity = {}", s1.len(), s1.capacity()); let mut s2 = String::with_capacity(s1.len() + 1); s2.push_str(&s1); s2.push('!'); println!("s2: len = {}, capacity = {}", s2.len(), s2.capacity()); let s3 = String::from("ðšð"); println!("s3: len = {}, number of chars = {}", s3.len(), s3.chars().count()); }
String 㯠Deref<Target = str> ãå®è£
ããŠãããããString ã«å¯Ÿã㊠str ã®ãã¹ãŠã®ã¡ãœãããåŒã³åºããŸãã
String::newã¯æ°ããç©ºã®æååãè¿ããŸããæååã«è¿œå ãããããŒã¿éãåãã£ãŠããå Žåã¯String::with_capacityã䜿ã£ãŠãã ãããString::lenã¯Stringã®ãµã€ãºããã€ãåäœã§è¿ããŸãïŒããã¯æåæ°ãšããŠã®é·ããšã¯ç°ãªãå ŽåããããŸãïŒãString::charsã¯å®éã®æåãå埩ããã€ãã¬ãŒã¿ãè¿ããŸããæžèšçŽ ã¯ã©ã¹ã¿ ã«ãããcharã¯äººéããæåããšèŠãªããã®ãšã¯ç°ãªãå Žåãããããšã«æ³šæããŠãã ããã- æååã«èšåãããšããããã¯
&strãŸãã¯Stringã®ã©ã¡ãããæããŠããå ŽåããããŸãã - åã
Deref<Target = T>ãå®è£ ããŠãããšãã³ã³ãã€ã©ã«ãã£ãŠTã®ã¡ãœãããééçã«åŒã³åºããããã«ãªããŸãã- ãŸã
Derefãã¬ã€ãã«ã€ããŠã¯èª¬æããŠããªãã®ã§ããã®æç¹ã§ã¯äž»ã«ããã¥ã¡ã³ãã®ãµã€ãããŒã®æ§é ã説æãããã®ã§ãã Stringã¯Deref<Target = str>ãå®è£ ããŠãããããstrã®ã¡ãœããã«ééçã«ã¢ã¯ã»ã¹ã§ããŸããlet s3 = s1.deref();ãšlet s3 = &*s1;ãæžããŠæ¯èŒããŠã¿ãŠãã ããã
- ãŸã
Stringã¯ãã€ããã¯ã¿ãå ãã©ãããŒãšããŠå®è£ ãããŠããããã¯ã¿ã§ãµããŒããããŠããå€ãã®æäœã¯Stringã§ããµããŒããããŠããŸãããããã€ã远å ã®ä¿èšŒããããŸããStringã«ã€ã³ããã¯ã¹ã¢ã¯ã»ã¹ããããŸããŸãªæ¹æ³ãæ¯èŒããŠãã ãã:- æåã«å¯ŸããŠã¯ã
iãç¯å²å ã®å Žåãšç¯å²å€ã®å Žåã§s3.chars().nth(i).unwrap()ã䜿ããŸãã - éšåæååã«å¯ŸããŠã¯ã
s3[0..4]ã䜿ãããã®ã¹ã©ã€ã¹ãæåå¢çã«ããå Žåãšãªãå Žåã詊ããŸãã
- æåã«å¯ŸããŠã¯ã
- å€ãã®åã¯
to_stringã¡ãœããã§æååã«å€æã§ããŸãããã®ãã¬ã€ãã¯Displayãå®è£ ãããã¹ãŠã®åã«å¯ŸããŠèªåçã«å®è£ ãããããããã©ãŒãããã§ãããã®ã¯ãã¹ãŠæååã«ã倿ã§ããŸãã
Vec
Vec ã¯ãæšæºã®ãµã€ãºå€æŽå¯èœãªããŒãå²ãåœãŠãããã¡ã§ã:
// Copyright 2023 Google LLC // SPDX-License-Identifier: Apache-2.0 fn main() { let mut v1 = Vec::new(); v1.push(42); println!("v1: len = {}, capacity = {}", v1.len(), v1.capacity()); let mut v2 = Vec::with_capacity(v1.len() + 1); v2.extend(v1.iter()); v2.push(9999); println!("v2: len = {}, capacity = {}", v2.len(), v2.capacity()); // èŠçŽ ãæå®ããŠãã¯ã¿ãåæåããããã®æšæºçãªãã¯ãã let mut v3 = vec![0, 0, 1, 2, 3, 4]; // å¶æ°ã®èŠçŽ ã ããä¿æããã v3.retain(|x| x % 2 == 0); println!("{v3:?}"); // é£ç¶ããéè€èŠçŽ ãåé€ããã v3.dedup(); println!("{v3:?}"); }
Vec 㯠Deref<Target = [T]> ãå®è£
ããŠãããããVec ã«å¯ŸããŠã¹ã©ã€ã¹ã®ã¡ãœãããåŒã³åºããŸãã
Vecã¯ãStringãHashMapãšåæ§ã«ã³ã¬ã¯ã·ã§ã³åã®äžçš®ã§ããå«ãŸããããŒã¿ã¯ããŒãã«æ ŒçŽãããŸããã€ãŸããããŒã¿éã¯ã³ã³ãã€ã«æã«åãã£ãŠããå¿ èŠããããŸãããå®è¡æã«å¢ãããæžã£ããã§ããŸããVec<T>ããžã§ããªãã¯åã§ãããTãæç€ºçã«æå®ããå¿ èŠã¯ãããŸãããRust ã®åæšè«ã§ã¯ãã€ãã®ããã«ãTã¯æåã®pushåŒã³åºãã§æ±ºãŸããŸããvec![...]ã¯Vec::new()ã®ä»£ããã«äœ¿ãæšæºçãªãã¯ãã§ããã¯ã¿ã«åæèŠçŽ ã远å ã§ããŸãã- ãã¯ã¿ã«ã€ã³ããã¯ã¹ã§ã¢ã¯ã»ã¹ããã«ã¯
[]ã䜿ããŸãããç¯å²å€ã ãš panic ããŸãã代ããã«getã䜿ããšOptionãè¿ããŸããpop颿°ã¯æåŸã®èŠçŽ ãåé€ããŸãã
HashMap
HashDoS æ»æã«å¯Ÿããä¿è·ãåããæšæºã®ããã·ã¥ããã:
// Copyright 2023 Google LLC // SPDX-License-Identifier: Apache-2.0 use std::collections::HashMap; fn main() { let mut page_counts = HashMap::new(); page_counts.insert("Adventures of Huckleberry Finn", 207); page_counts.insert("Grimms' Fairy Tales", 751); page_counts.insert("Pride and Prejudice", 303); if !page_counts.contains_key("Les Misérables") { println!( "We know about {} books, but not Les Misérables.", page_counts.len() ); } for book in ["Pride and Prejudice", "Alice's Adventure in Wonderland"] { match page_counts.get(book) { Some(count) => println!("{book}: {count} pages"), None => println!("{book} is unknown."), } } // äœãèŠã€ãããªãã£ãå Žåã«å€ãæ¿å ¥ããã«ã¯ã.entry() ã¡ãœããã䜿çšããŸãã for book in ["Pride and Prejudice", "Alice's Adventure in Wonderland"] { let page_count: &mut i32 = page_counts.entry(book).or_insert(0); *page_count += 1; } dbg!(page_counts); }
-
HashMap㯠prelude ã«ã¯å«ãŸããŠããªããããã¹ã³ãŒãã«å°å ¥ããå¿ èŠããããŸãã -
次ã®ã³ãŒãè¡ã詊ããŠã¿ãŠãã ãããæåã®è¡ã¯ãæ¬ãããã·ã¥ãããå ã«ãããã©ããã確èªããèŠã€ãããªãå Žåã¯ä»£æ¿å€ãè¿ããŸãã2 è¡ç®ã¯ãæ¬ãèŠã€ãããªãå Žåã«ãã®ä»£æ¿å€ãããã·ã¥ãããã«æ¿å ¥ããŸãã
// Copyright 2023 Google LLC // SPDX-License-Identifier: Apache-2.0 let pc1 = page_counts .get("Harry Potter and the Sorcerer's Stone") .unwrap_or(&336); let pc2 = page_counts .entry("The Hunger Games") .or_insert(374); -
vec!ãšã¯ç°ãªããæ®å¿µãªããæšæºã®hashmap!ãã¯ãã¯ãããŸããã-
ãã ããRust 1.56 以éãHashMap ã¯
From<[(K, V); N]>ãå®è£ ããŠãããããã«ããé åãªãã©ã«ããããã·ã¥ããããç°¡åã«åæåã§ããŸã:// Copyright 2023 Google LLC // SPDX-License-Identifier: Apache-2.0 let page_counts = HashMap::from([ ("Harry Potter and the Sorcerer's Stone".to_string(), 336), ("The Hunger Games".to_string(), 374), ]);
-
-
ãŸããHashMap ã¯ããŒãšå€ã®ã¿ãã«ãçæããä»»æã®
Iteratorããæ§ç¯ã§ããŸãã -
ãã®åã«ã¯ã
std::collections::hash_map::Keysã®ãããªãã¡ãœããåºæãã®æ»ãå€åãããã€ããããŸãããããã®å㯠Rust ã®ããã¥ã¡ã³ããæ€çŽ¢ãããšããçŸããŸãããã®åã®ããã¥ã¡ã³ããšãkeysã¡ãœãããžæ»ãããã®äŸ¿å©ãªãªã³ã¯ãåè¬è ã«ç€ºããŠãã ããã
æŒç¿: Counter
ãã®æŒç¿ã§ã¯ãéåžžã«åçŽãªããŒã¿æ§é ãåãäžããŠãããããžã§ããªãã¯ã«ããŸãã ããã¯ã std::collections::HashMap ã䜿ã£ãŠãã©ã®å€ãçŸããããšããããããäœååºçŸãããã远跡ããŸãã
Counter ã®åæããŒãžã§ã³ã¯ãu32 å€ã§ããåäœããªãããã«ããŒãã³ãŒããããŠããŸãã 远跡ããå€ã®åã«å¯Ÿã㊠struct ãšãã®ã¡ãœããããžã§ããªãã¯ã«ãããã®ããã«ã㊠Counter ãä»»æã®åã®å€ã远跡ã§ããããã«ããŠãã ããã
æ©ãçµãã£ããã entry ã¡ãœããã䜿ã£ãŠãcount ã¡ãœããã®å®è£
ã«å¿
èŠãªããã·ã¥æ€çŽ¢ã®åæ°ãååã«ããŠã¿ãŠãã ããã
// Copyright 2023 Google LLC // SPDX-License-Identifier: Apache-2.0 use std::collections::HashMap; /// Counter ã¯ãå T ã®åå€ãçŸããåæ°ãæ°ããŸãã struct Counter { values: HashMap<u32, u64>, } impl Counter { /// æ°ãã Counter ãäœæããŸãã fn new() -> Self { Counter { values: HashMap::new(), } } /// æå®ãããå€ã®åºçŸãæ°ããŸãã fn count(&mut self, value: u32) { if self.values.contains_key(&value) { *self.values.get_mut(&value).unwrap() += 1; } else { self.values.insert(value, 1); } } /// æå®ãããå€ãçŸããåæ°ãè¿ããŸãã fn times_seen(&self, value: u32) -> u64 { self.values.get(&value).copied().unwrap_or_default() } } fn main() { let mut ctr = Counter::new(); ctr.count(13); ctr.count(14); ctr.count(16); ctr.count(14); ctr.count(14); ctr.count(11); for i in 10..20 { println!("saw {} values equal to {}", ctr.times_seen(i), i); } let mut strctr = Counter::new(); strctr.count("apple"); strctr.count("orange"); strctr.count("apple"); println!("got {} apples", strctr.times_seen("apple")); }
è§£ç
// Copyright 2023 Google LLC // SPDX-License-Identifier: Apache-2.0 use std::collections::HashMap; use std::hash::Hash; /// Counter counts the number of times each value of type T has been seen. struct Counter<T> { values: HashMap<T, u64>, } impl<T: Eq + Hash> Counter<T> { /// Create a new Counter. fn new() -> Self { Counter { values: HashMap::new() } } /// Count an occurrence of the given value. fn count(&mut self, value: T) { *self.values.entry(value).or_default() += 1; } /// Return the number of times the given value has been seen. fn times_seen(&self, value: T) -> u64 { self.values.get(&value).copied().unwrap_or_default() } } fn main() { let mut ctr = Counter::new(); ctr.count(13); ctr.count(14); ctr.count(16); ctr.count(14); ctr.count(14); ctr.count(11); for i in 10..20 { println!("saw {} values equal to {}", ctr.times_seen(i), i); } let mut strctr = Counter::new(); strctr.count("apple"); strctr.count("orange"); strctr.count("apple"); println!("got {} apples", strctr.times_seen("apple")); }
æšæºã©ã€ãã©ãªã®ãã¬ã€ã
segment outline
æšæºã©ã€ãã©ãªã®åãšåæ§ã«ãåãã¬ã€ãã®ããã¥ã¡ã³ãã確èªããæéãåã£ãŠãã ããã
ãã®ã»ã¯ã·ã§ã³ã¯é·ãã§ããéäžã§äŒæ©ãåããŸãããã
æ¯èŒ
ãããã®ãã¬ã€ãã¯å€åå£«ã®æ¯èŒããµããŒãããŸãããããã®ãã¬ã€ããå®è£ ãããã£ãŒã«ããå«ãåã§ã¯ããããã®ãã¬ã€ãããã¹ãŠå°åºã§ããŸãã
PartialEq ãš Eq
PartialEq ã¯éšååå€é¢ä¿ã§ãããå¿
é ã¡ãœãã eq ãšãããã©ã«ãå®è£
ãããã¡ãœãã ne ãæã¡ãŸãã== æŒç®åãš != æŒç®åã¯ãããã®ã¡ãœãããåŒã³åºããŸãã
// èäœæš© 2023 Google LLC // SPDX-License-Identifier: Apache-2.0 struct Key { id: u32, metadata: Option<String>, } impl PartialEq for Key { fn eq(&self, other: &Self) -> bool { self.id == other.id } }
Eq ã¯å®å
šãªåå€é¢ä¿ïŒåå°çã察称çãæšç§»çïŒã§ãããPartialEq ã嫿ããŸããå®å
šãªåå€é¢ä¿ãå¿
èŠãšãã颿°ã§ã¯ããã¬ã€ãå¢çãšã㊠Eq ã䜿çšããŸãã
PartialOrd ãš Ord
PartialOrd ã¯ãpartial_cmp ã¡ãœãããæã€åé åºãå®çŸ©ããŸãããã㯠<ã<=ã>=ã> æŒç®åãå®è£
ããããã«äœ¿ãããŸãã
// èäœæš© 2023 Google LLC // SPDX-License-Identifier: Apache-2.0 use std::cmp::Ordering; #[derive(Eq, PartialEq)] struct Citation { author: String, year: u32, } impl PartialOrd for Citation { fn partial_cmp(&self, other: &Self) -> Option<Ordering> { match self.author.partial_cmp(&other.author) { Some(Ordering::Equal) => self.year.partial_cmp(&other.year), author_ord => author_ord, } } }
Ord ã¯ãcmp ã Ordering ãè¿ãå
šé åºã§ãã
-
PartialEqã¯ç°ãªãåã®éã§ãå®è£ ã§ããŸãããEqã¯åå°çã§ããããã§ããŸãã:// èäœæš© 2023 Google LLC // SPDX-License-Identifier: Apache-2.0 struct Key { id: u32, metadata: Option<String>, } impl PartialEq<u32> for Key { fn eq(&self, other: &u32) -> bool { self.id == *other } } -
å®éã«ã¯ããããã®ãã¬ã€ãã¯å°åºããã®ãäžè¬çã§ãããå®è£ ããããšã¯ããŸããããŸããã
-
Rust ã§åç §ãæ¯èŒãããšãã¯ãåç §ãã®ãã®ã§ã¯ãªããåç §å ã®å€ãæ¯èŒãããŸããã€ãŸããåç §å ã®å€ãåãã§ããã°ãç°ãªã 2 ã€ã®ãã®ãžã®åç §ã§ãçãããšæ¯èŒãããããšããããŸã:
// èäœæš© 2023 Google LLC // SPDX-License-Identifier: Apache-2.0 fn main() { let a = "Hello"; let b = String::from("Hello"); assert_eq!(a, b); }
æŒç®å
æŒç®åãªãŒããŒããŒã㯠std::ops ã®ãã¬ã€ããéããŠå®è£
ãããŸãã
// Copyright 2023 Google LLC // SPDX-License-Identifier: Apache-2.0 #[derive(Debug, Copy, Clone)] struct Point { x: i32, y: i32, } impl std::ops::Add for Point { type Output = Self; fn add(self, other: Self) -> Self { Self { x: self.x + other.x, y: self.y + other.y } } } fn main() { let p1 = Point { x: 10, y: 20 }; let p2 = Point { x: 100, y: 200 }; println!("{p1:?} + {p2:?} = {:?}", p1 + p2); }
è°è«ã®ãã€ã³ã:
&Pointã«å¯ŸããŠAddãå®è£ ããããšãã§ããŸããããã¯ã©ã®ãããªç¶æ³ã§åœ¹ç«ã€ã§ãããã?- åç:
Add:addã¯selfãæ¶è²»ããŸããæŒç®åããªãŒããŒããŒããã察象ã®åTãCopyã§ãªãå Žåã¯ã&Tã«å¯ŸããŠãæŒç®åããªãŒããŒããŒãããããšãæ€èšãã¹ãã§ããããã«ãããåŒã³åºãåŽã§äžèŠãªã¯ããŒã³ãé¿ããããŸãã
- åç:
Outputãé¢é£åãªã®ã¯ãªãã§ãããã? ãããã¡ãœããã®åãã©ã¡ãŒã¿ã«ããããšã¯ã§ããã§ãããã?- çãçã: 颿°ã®åãã©ã¡ãŒã¿ã¯åŒã³åºãåŽãå¶åŸ¡ããŸãããé¢é£åïŒ
Outputã®ãããªãã®ïŒã¯ãã¬ã€ãã®å®è£ è ãå¶åŸ¡ããŸãã
- çãçã: 颿°ã®åãã©ã¡ãŒã¿ã¯åŒã³åºãåŽãå¶åŸ¡ããŸãããé¢é£åïŒ
- 2 ã€ã®ç°ãªãåã«å¯ŸããŠ
Addãå®è£ ããããšãã§ããŸããããšãã°ãimpl Add<(i32, i32)> for Pointã¯ã¿ãã«ãPointã«å ç®ããŸãã
Not ãã¬ã€ãïŒ! æŒç®åïŒã¯ãC ç³»èšèªã®åãæŒç®åã®ããã«åŒæ°ã bool ã«å€æããªããããæ³šç®ã«å€ããŸãã代ããã«ãæŽæ°åã«å¯ŸããŠã¯æ°å€ã®åããããå転ããŸããããã¯ç®è¡çã«ã¯ãåŒæ°ã -1 ããæžç®ããããšãšç䟡ã§ã: !5 == -6ã
From ãš Into
å㯠From ãš Into ãå®è£
ããŠãå倿ã容æã«ããŸãã as ãšã¯ç°ãªãããããã®ãã¬ã€ãã¯æ
å ±ã倱ããã倱æããªã倿ã«å¯Ÿå¿ããŸãã
// èäœæš© 2023 Google LLC // SPDX-License-Identifier: Apache-2.0 fn main() { let s = String::from("hello"); let addr = std::net::Ipv4Addr::from([127, 0, 0, 1]); let one = i16::from(true); let bigger = i32::from(123_i16); println!("{s}, {addr}, {one}, {bigger}"); }
From ãå®è£
ããããšãInto ã¯èªåçã«å®è£
ãããŸãã
// èäœæš© 2023 Google LLC // SPDX-License-Identifier: Apache-2.0 fn main() { let s: String = "hello".into(); let addr: std::net::Ipv4Addr = [127, 0, 0, 1].into(); let one: i16 = true.into(); let bigger: i32 = 123_i16.into(); println!("{s}, {addr}, {one}, {bigger}"); }
- ãã®ãããéåžžã¯
Fromã ããå®è£ ããã®ãäžè¬çã§ããããããã°ãããªãã®åã¯Intoã®å®è£ ãåŸãããŸãã - ã
Stringã«å€æã§ããä»»æã®ãã®ãã®ãããªé¢æ°åŒæ°ã®å ¥ååã宣èšããå Žåã¯ãéã®ã«ãŒã«ã«ãªããŸããIntoã䜿ãã¹ãã§ããããããããšã§ããã®é¢æ°ã¯Fromãå®è£ ããåãšãIntoã®ã¿ãå®è£ ããåã®äž¡æ¹ãåãåããŸãã
ãã£ã¹ã
Rust ã«ã¯ æé»ç㪠å倿ã¯ãããŸããããas ã«ããæç€ºçãªãã£ã¹ãã¯ãµããŒããããŠããŸãããããã¯ãå®çŸ©ãããŠããç¯å²ã§ã¯äžè¬ã« C ã®ã»ãã³ãã£ã¯ã¹ã«åŸããŸãã
// Copyright 2023 Google LLC // SPDX-License-Identifier: Apache-2.0 fn main() { let value: i64 = 1000; println!("as u16: {}", value as u16); println!("as i16: {}", value as i16); println!("as u8: {}", value as u8); }
as ã®çµæã¯ Rust ã§ã¯ åžžã« å®çŸ©ãããŠããããã©ãããã©ãŒã éã§äžè²«ããŠããŸããããã¯ã笊å·ãå€ããããããå°ããåã«ãã£ã¹ããããããå Žåã®çŽæã«åããªãããšããããŸããããã¥ã¡ã³ãã確èªããæç¢ºã«ããããã®ã³ã¡ã³ããæ·»ããŠãã ããã
as ã«ãããã£ã¹ãã¯æ¯èŒçéå©ãªããŒã«ã§ã誀ã£ãŠäœ¿ãããããå°æ¥ã®ä¿å®äœæ¥ã§äœ¿çšãããåãåå
ã®å€ã®ç¯å²ãå€ãããšã埮åŠãªãã°ã®åå ã«ãªãåŸãŸãããã£ã¹ãã¯ãç¡æ¡ä»¶ã®åãæšãŠãæå³ããŠããããšã瀺ãããå Žåã«ã®ã¿äœ¿ãã®ãæåã§ãïŒããšãã°ãé«äœãããã«äœãå
¥ã£ãŠãããã«é¢ä¿ãªããu64 ã®äžäœ 32 ãããã as u32 ã§éžæããå ŽåïŒã
倱æããªããã£ã¹ãïŒããšãã° u32 ãã u64ïŒã§ã¯ããã®ãã£ã¹ããå®éã«å€±æããªãããšãæç¢ºã«ãããããas ããã From ã Into ã䜿ãããšãåªå
ããŠãã ããã倱æããå¯èœæ§ã®ãããã£ã¹ãã§ã¯ãåãŸããã®ãšåãŸããªããã®ãåããŠæ±ãããå Žåã« TryFrom ãš TryInto ãå©çšã§ããŸãã
ãã®ã¹ã©ã€ãã®åŸã§äŒæ©ãåãããšãæ€èšããŠãã ããã
as 㯠C++ ã® static cast ã«äŒŒãŠããŸããããŒã¿ã倱ãããå¯èœæ§ãããå Žåã® as ã®äœ¿çšã¯ãäžè¬ã«æšå¥šãããŸãããå°ãªããšã説æã³ã¡ã³ããä»ããã¹ãã§ãã
ããã¯ãã€ã³ããã¯ã¹ãšããŠäœ¿ãããã«æŽæ°ã usize ã«ãã£ã¹ãããå Žåã«ããèŠãããŸãã
Read ãš Write
Read ãš BufRead ã䜿ããšãu8 ã®ãœãŒã¹ãæœè±¡åã§ããŸãã
// Copyright 2023 Google LLC // SPDX-License-Identifier: Apache-2.0 use std::io::{BufRead, BufReader, Read, Result}; fn count_lines<R: Read>(reader: R) -> usize { let buf_reader = BufReader::new(reader); buf_reader.lines().count() } fn main() -> Result<()> { let slice: &[u8] = b"foo\nbar\nbaz\n"; println!("lines in slice: {}", count_lines(slice)); let file = std::fs::File::open(std::env::current_exe()?)?; println!("lines in file: {}", count_lines(file)); Ok(()) }
åæ§ã«ãWrite ã䜿ããš u8 ã®ã·ã³ã¯ãæœè±¡åã§ããŸãã
// Copyright 2023 Google LLC // SPDX-License-Identifier: Apache-2.0 use std::io::{Result, Write}; fn log<W: Write>(writer: &mut W, msg: &str) -> Result<()> { writer.write_all(msg.as_bytes())?; writer.write_all("\n".as_bytes()) } fn main() -> Result<()> { let mut buffer = Vec::new(); log(&mut buffer, "Hello")?; log(&mut buffer, "World")?; println!("Logged: {buffer:?}"); Ok(()) }
Default ãã¬ã€ã
Default ãã¬ã€ãã¯ãåã®ããã©ã«ãå€ãçæããŸãã
// èäœæš© 2023 Google LLC // SPDX-License-Identifier: Apache-2.0 #[derive(Debug, Default)] struct Derived { x: u32, y: String, z: Implemented, } #[derive(Debug)] struct Implemented(String); impl Default for Implemented { fn default() -> Self { Self("John Smith".into()) } } fn main() { let default_struct = Derived::default(); dbg!(default_struct); let almost_default_struct = Derived { y: "Y is set!".into(), ..Derived::default() }; dbg!(almost_default_struct); let nothing: Option<Derived> = None; dbg!(nothing.unwrap_or_default()); }
- ããã¯çŽæ¥å®è£
ããããšãã
#[derive(Default)]ã§å°åºããããšãã§ããŸãã - å°åºãããå®è£
ã¯ããã¹ãŠã®ãã£ãŒã«ããããããã®ããã©ã«ãå€ã«èšå®ãããå€ãçæããŸãã
- ããã¯ãæ§é äœå
ã®ãã¹ãŠã®åã
Defaultãå®è£ ããŠããå¿ èŠãããããšãæå³ããŸãã
- ããã¯ãæ§é äœå
ã®ãã¹ãŠã®åã
- Rust ã®æšæºã©ã€ãã©ãªã®åã®å€ãã¯ã劥åœãªå€ïŒäŸ:
0ã""ãªã©ïŒã§Defaultãå®è£ ããŠããŸãã - æ§é äœã®éšååæåã¯ãããã©ã«ãå€ãšçµã¿åããããšããŸãæ©èœããŸãã
- Rust æšæºã©ã€ãã©ãªã¯ãåã
Defaultãå®è£ ã§ããããšãèæ ®ããŠããããããå©çšãã䟿å©ãªã¡ãœãããæäŸããŠããŸãã ..æ§æã¯ æ§é äœæŽæ°æ§æ ãšåŒã°ããŸãã
æŒç¿: ROT13
ãã®äŸã§ã¯ãå€å žç㪠âROT13â æå· ãå®è£ ããŸãããã®ã³ãŒãã ãã¬ã€ã°ã©ãŠã³ãã«ã³ããŒããäžè¶³ããŠããéšåãå®è£ ããŠãã ãããçµæãåŒãç¶ãæå¹ãª UTF-8 ã«ãªãããã«ãASCII ã®è±åã®ã¿ãå転ãããŠãã ããã
// Copyright 2023 Google LLC // SPDX-License-Identifier: Apache-2.0 use std::io::Read; struct RotDecoder<R: Read> { input: R, rot: u8, } // `RotDecoder` ã«å¯Ÿã㊠`Read` ãã¬ã€ããå®è£ ããŸãã #[cfg(test)] mod test { use super::*; #[test] fn joke() { let mut rot = RotDecoder { input: "Gb trg gb gur bgure fvqr!".as_bytes(), rot: 13 }; let mut result = String::new(); rot.read_to_string(&mut result).unwrap(); assert_eq!(&result, "To get to the other side!"); } #[test] fn binary() { let input: Vec<u8> = (0..=255u8).collect(); let mut rot = RotDecoder::<&[u8]> { input: input.as_slice(), rot: 13 }; let mut buf = [0u8; 256]; assert_eq!(rot.read(&mut buf).unwrap(), 256); for i in 0..=255 { if input[i] != buf[i] { assert!(input[i].is_ascii_alphabetic()); assert!(buf[i].is_ascii_alphabetic()); } } } }
ãããã 13 æåå転ãã 2 ã€ã® RotDecoder ã€ã³ã¹ã¿ã³ã¹ãé£çµãããšãäœãèµ·ããã§ããããïŒ
è§£ç
// Copyright 2023 Google LLC // SPDX-License-Identifier: Apache-2.0 use std::io::Read; struct RotDecoder<R: Read> { input: R, rot: u8, } impl<R: Read> Read for RotDecoder<R> { fn read(&mut self, buf: &mut [u8]) -> std::io::Result<usize> { let size = self.input.read(buf)?; for b in &mut buf[..size] { if b.is_ascii_alphabetic() { let base = if b.is_ascii_uppercase() { 'A' } else { 'a' } as u8; *b = (*b - base + self.rot) % 26 + base; } } Ok(size) } } #[cfg(test)] mod test { use super::*; #[test] fn joke() { let mut rot = RotDecoder { input: "Gb trg gb gur bgure fvqr!".as_bytes(), rot: 13 }; let mut result = String::new(); rot.read_to_string(&mut result).unwrap(); assert_eq!(&result, "To get to the other side!"); } #[test] fn binary() { let input: Vec<u8> = (0..=255u8).collect(); let mut rot = RotDecoder::<&[u8]> { input: input.as_slice(), rot: 13 }; let mut buf = [0u8; 256]; assert_eq!(rot.read(&mut buf).unwrap(), 256); for i in 0..=255 { if input[i] != buf[i] { assert!(input[i].is_ascii_alphabetic()); assert!(buf[i].is_ascii_alphabetic()); } } } }
Day 3 ãžãããã
ããã§ãã³ã¢ãšãªãèšèªæ©èœããã¹ãŠèŠãŠããŸããã
- åºç€: åºæ¬çãªåãå¶åŸ¡ãããŒã颿°ãããŒã¿æ§é ã
- ãã¿ãŒã³ãããã³ã°: ããŒã¿ã广çã«åè§£ããããšã
- ããªã¢ãŒãã£ãºã : ã¡ãœãããTraitãGenericsã
- æšæºã©ã€ãã©ãª:
OptionãResultãVecãStringã®ãããªéèŠãªåã䜿ãããšã - ã¯ããŒãžã£: ç°å¢ããã£ããã£ã§ããç¡å颿°ã
ããããåãèšè¿°ããããã«æ¯ãèããé¢é£ä»ããããšãã§ããŸããããããã¯èŠç¹ãåãæ¿ããŠã ãããã®æŠå¿µãã¡ã¢ãªç®¡çãšã·ã¹ãã èšèšã«é©çšããŠãããŸãã
ã¹ã±ãžã¥ãŒã«
session outline
ã¡ã¢ãªç®¡ç
segment outline
ããã°ã©ã ã¡ã¢ãªã®ã¬ãã¥ãŒ
ããã°ã©ã 㯠2 ã€ã®æ¹æ³ã§ã¡ã¢ãªãå²ãåœãŠãŸã:
-
ã¹ã¿ãã¯: ããŒã«ã«å€æ°ã®ããã®é£ç¶ããã¡ã¢ãªé åã
- å€ã®ãµã€ãºã¯åºå®ã§ãã³ã³ãã€ã«æã«ããããŸãã
- éåžžã«é«é: ã¹ã¿ãã¯ãã€ã³ã¿ãåããã ãã§ãã
- 管çã容æ: 颿°åŒã³åºãã«åŸããŸãã
- ã¡ã¢ãªå±ææ§ãé«ãã§ãã
-
ããŒã: 颿°åŒã³åºãã®å€ã«ããå€ãæ ŒçŽããé åã
- å€ã®ãµã€ãºã¯åçã§ãå®è¡æã«æ±ºãŸããŸãã
- ã¹ã¿ãã¯ãããããã«äœé: å€å°ã®ç®¡çåŠçãå¿ èŠã§ãã
- ã¡ã¢ãªå±ææ§ã¯ä¿èšŒãããŸããã
äŸ
String ãäœæãããšãåºå®ãµã€ãºã®ã¡ã¿ããŒã¿ã¯ã¹ã¿ãã¯ã«ãåçãªãµã€ãºã® ããŒã¿ãã€ãŸãå®éã®æååã¯ããŒãã«é
眮ãããŸã:
// Copyright 2023 Google LLC // SPDX-License-Identifier: Apache-2.0 fn main() { let s1 = String::from("Hello"); }
-
Stringã¯å éšçã«Vecã«ãã£ãŠå®è£ ãããŠãããããcapacity ãš length ãæã¡ã å¯å€ã§ããã°ãããŒãäžã§ã®åå²ãåœãŠã«ãã£ãŠæ¡åŒµã§ããããšã«è§ŠããŠãã ããã -
åŠçããããã«ã€ããŠè³ªåãããã°ãåºç€ãšãªãã¡ã¢ãªã¯ System Allocator ã䜿çšããŠããŒãã« å²ãåœãŠãããŠãããã«ã¹ã¿ã ã¢ãã±ãŒã¿ã¯ Allocator API ã䜿ã£ãŠ å®è£ ã§ããããšã説æã§ããŸã
ããã«è©³ãã
unsafe Rust ã䜿ããšã¡ã¢ãªã¬ã€ã¢ãŠãã調ã¹ãããŸãããã ãããããåœç¶ unsafe ã§ããããšã¯ææããŠããã¹ãã§ãïŒ
// Copyright 2023 Google LLC // SPDX-License-Identifier: Apache-2.0 fn main() { let mut s1 = String::from("Hello"); s1.push(' '); s1.push_str("world"); // å®¶ã§ããã詊ããªãã§ãã ããïŒæè²ç®çã®ã¿ã§ãã // String ã¯ãã®ã¬ã€ã¢ãŠãã«ã€ããŠäœã®ä¿èšŒãããªããããããã«ãã // æªå®çŸ©åäœãçºçããå¯èœæ§ããããŸãã unsafe { let (capacity, ptr, len): (usize, usize, usize) = std::mem::transmute(s1); println!("capacity = {capacity}, ptr = {ptr:#x}, len = {len}"); } }
ã¡ã¢ãªç®¡çã®ã¢ãããŒã
åŸæ¥ãèšèªã¯å€§ãŸãã« 2 ã€ã®ã«ããŽãªã«åããããŠããŸããã
- æåã¡ã¢ãªç®¡çã«ããå®å
šãªå¶åŸ¡: C, C++, Pascal, âŠ
- ããã°ã©ããããã€ããŒãã¡ã¢ãªãå²ãåœãŠããè§£æŸãããããããæ±ºããŸãã
- ãã€ã³ã¿ãäŸç¶ãšããŠæå¹ãªã¡ã¢ãªãæããŠãããã©ããããããã°ã©ãã倿ããªããã°ãªããŸããã
- ç ç©¶ã瀺ãããã«ãããã°ã©ãã¯ãã¹ãç¯ããŸãã
- å®è¡æã®èªåã¡ã¢ãªç®¡çã«ããå®å
šãªå®å
šæ§: Java, Python, Go, Haskell, âŠ
- ã©ã³ã¿ã€ã ã·ã¹ãã ããã¡ã¢ãªãåç §ã§ããªããªããŸã§è§£æŸãããªãããšã ä¿èšŒããŸãã
- éåžžã¯ãåç §ã«ãŠã³ããŸãã¯ã¬ããŒãžã³ã¬ã¯ã·ã§ã³ã§å®è£ ãããŸãã
Rust ã¯æ°ããªçµã¿åãããæäŸããŸãã
æ£ããã¡ã¢ãªç®¡çãã³ã³ãã€ã«æã«åŒ·å¶ããããšã«ãããå®å šãªå¶åŸ¡ ãš å®å šæ§ã
ããã¯ãæç€ºçãªæææš©ã®æŠå¿µã«ãã£ãŠå®çŸãããŠããŸãã
ãã®ã¹ã©ã€ãã¯ãä»ã®èšèªããæ¥ãåè¬è ã Rust ãæèã®äžã§äœçœ®ã¥ã㊠çè§£ããã®ã«åœ¹ç«ã€ããšãæå³ããŠããŸãã
-
C ã§ã¯ã
mallocãšfreeã䜿ã£ãŠããŒããæåã§ç®¡çããªããã°ãªããŸããããããããšã©ãŒã«ã¯ãfreeã®åŒã³åºãå¿ããåããã€ã³ã¿ã«å¯ŸããŠè€æ°ååŒã³åºãããšããããã¯ãã®ãã€ã³ã¿ãæããŠãã ã¡ã¢ãªããã§ã«è§£æŸãããåŸã«ãã®ãã€ã³ã¿ãããªãã¡ã¬ã³ã¹ããããšãå«ãŸããŸãã -
C++ ã«ã¯ãã¹ããŒããã€ã³ã¿ïŒ
unique_ptr,shared_ptrïŒã®ãããªããŒã«ãããã ãã¹ãã©ã¯ã¿åŒã³åºãã«é¢ããèšèªã®ä¿èšŒã掻çšããŠã颿°ããæ»ããšãã«ã¡ã¢ãªã è§£æŸãããããšã確å®ã«ããŸããããã§ããªãããããã®ããŒã«ã誀çšããŠã C ãšåæ§ã®ãã°ãäœã蟌ãã§ããŸãã®ã¯ããªãç°¡åã§ãã -
JavaãGoãPython ã¯ããã¯ãå°éäžèœã«ãªã£ãã¡ã¢ãªãã¬ããŒãžã³ã¬ã¯ã¿ãç¹å®ããŠ å»æ£ããããšã«äŸåããŠããŸããããã«ããããããããã€ã³ã¿ãããªãã¡ã¬ã³ã¹ã§ããããšã ä¿èšŒãããuse-after-free ããã®ä»ã®çš®é¡ã®ãã°ãæé€ãããŸããããããGC ã«ã¯å®è¡æã³ã¹ãããããé©åã«ãã¥ãŒãã³ã°ããã®ã¯å°é£ã§ãã
Rust ã®æææš©ãšåçšã®ã¢ãã«ã¯ãå€ãã®å Žåãå¿ èŠãªç®æã«æ£ç¢ºã« alloc ãš free ã® æäœãé 眮ããªãããC ã®æ§èœãå®çŸã§ããŸã â ãŒãã³ã¹ãã§ãããŸããC++ ã® ã¹ããŒããã€ã³ã¿ã«äŒŒãããŒã«ãæäŸããŸããå¿ èŠã«å¿ããŠãåç §ã«ãŠã³ãã®ãã㪠ä»ã®éžæè¢ãå©çšã§ããå®è¡æã¬ããŒãžã³ã¬ã¯ã·ã§ã³ããµããŒãããã¯ã¬ãŒããã ååšããŸãïŒãã®ææ¥ã§ã¯æ±ããŸããïŒã
æææš©
ãã¹ãŠã®å€æ°æçžã«ã¯ããããæå¹ãª ã¹ã³ãŒã ãããããã®ã¹ã³ãŒãå€ã§å€æ°ã䜿çšãããšãšã©ãŒã«ãªããŸãã
// èäœæš© 2023 Google LLC // SPDX-License-Identifier: Apache-2.0 struct Point(i32, i32); fn main() { { let p = Point(3, 4); dbg!(p.0); } dbg!(p.1); }
ãã®å€æ°ããã®å€ã ææããŠãã ãšèšããŸãããã¹ãŠã® Rust ã®å€ã«ã¯ãåžžã«ã¡ããã© 1 ã€ã®ææè ãããŸãã
ã¹ã³ãŒãã®çµããã§ã倿°ã¯ ãããã ãããããŒã¿ã¯è§£æŸãããŸããããã§ã¯ãã¹ãã©ã¯ã¿ãå®è¡ããããªãœãŒã¹ãè§£æŸã§ããŸãã
ã¬ããŒãžã³ã¬ã¯ã·ã§ã³ã®å®è£ ã«æ £ããŠããåè¬è ã§ããã°ãã¬ããŒãžã³ã¬ã¯ã¿ããã«ãŒããã®éåããéå§ããŠãå°éå¯èœãªãã¹ãŠã®ã¡ã¢ãªãèŠã€ããããšãç¥ã£ãŠããã§ããããRust ã®ãåäžææè ãã®ååããããã«äŒŒãèãæ¹ã§ãã
ã ãŒãã»ãã³ãã£ã¯ã¹
ä»£å ¥ãè¡ããšã倿°éã§_æææš©_ãç§»åããŸãïŒ
// èäœæš© 2023 Google LLC // SPDX-License-Identifier: Apache-2.0 fn main() { let s1 = String::from("Hello!"); let s2 = s1; dbg!(s2); // dbg!(s1); }
s1ããs2ãžã®ä»£å ¥ã«ãã£ãŠæææš©ãç§»åããŸããs1ãã¹ã³ãŒããæããŠããäœãèµ·ãããŸãããäœãææããŠããªãããã§ããs2ãã¹ã³ãŒããæãããšãæååããŒã¿ã¯è§£æŸãããŸãã
s2 ãžã ãŒãããåïŒ
s2 ãžã ãŒãããåŸïŒ
颿°ã«å€ãæž¡ããšããã®å€ã¯é¢æ° ãã©ã¡ãŒã¿ã«ä»£å ¥ãããŸããããã«ããæææš©ãç§»åããŸãïŒ
// èäœæš© 2023 Google LLC // SPDX-License-Identifier: Apache-2.0 fn say_hello(name: String) { println!("Hello {name}") } fn main() { let name = String::from("Alice"); say_hello(name); // say_hello(name); }
-
ãã㯠C++ ã®ããã©ã«ããšã¯éã§ããããšã«ãè§ŠããŠãã ãããC++ ã§ã¯
std::moveã䜿ããªãéã倿ž¡ãã§ã³ããŒãããŸãïŒãããŠã ãŒãã³ã³ã¹ãã©ã¯ã¿ãå®çŸ©ãããŠããå Žåã§ãïŒïŒã -
ç§»åããã®ã¯æææš©ã ãã§ããããŒã¿ãã®ãã®ãæäœããããã®ãã·ã³ã³ãŒãã çæããããã©ããã¯æé©åã®åé¡ã§ããããã®ãããªã³ããŒã¯ ç©æ¥µçã«æé©åã§åãé€ãããŸãã
-
åçŽãªå€ïŒæŽæ°ãªã©ïŒã«ã¯
Copyãä»ããããŸãïŒåŸã®ã¹ã©ã€ããåç §ïŒã -
Rust ã§ã¯ãã¯ããŒã³ã¯æç€ºçã§ãïŒ
cloneã䜿ããŸãïŒã
say_hello ã®äŸã§ã¯ïŒ
- æåã®
say_helloåŒã³åºãã§ãmainã¯nameã®æææš©ãææŸããŸãã ãã®åŸãmainã®äžã§ã¯nameããã䜿ããŸããã nameã®ããã«ç¢ºä¿ãããããŒãã¡ã¢ãªã¯ãsay_hello颿°ã®çµããã§ è§£æŸãããŸããmainã¯ãnameãåç §ïŒ&nameïŒãšããŠæž¡ãããã€say_helloã ãã©ã¡ãŒã¿ãšããŠåç §ãåãåããªããæææš©ãä¿æã§ããŸãã- ãããã¯ã
mainã¯æåã®åŒã³åºãã§nameã®ã¯ããŒã³ ïŒname.clone()ïŒãæž¡ãããšãã§ããŸãã - Rust ã¯ãã ãŒãã»ãã³ãã£ã¯ã¹ãããã©ã«ãã«ããããã°ã©ãã«ã¯ããŒã³ã æç€ºãããããšã§ãC++ ãããæå³ããã³ããŒãäœãã«ããããŠããŸãã
ããã«è©³ãã
çŸä»£ã® C++ ã«ãããé²åŸ¡çã³ããŒ
çŸä»£ã® C++ ã§ã¯ãããã¯å¥ã®æ¹æ³ã§è§£æ±ºããŸãïŒ
std::string s1 = "Cpp";
std::string s2 = s1; // s1 ã®ããŒã¿ãè€è£œããã
s1ã®ããŒãããŒã¿ã¯è€è£œãããs2ã¯ããèªèº«ã®ç¬ç«ããã³ããŒãæã¡ãŸããs1ãšs2ãã¹ã³ãŒããæãããšããããããèªåã®ã¡ã¢ãªãè§£æŸããŸãã
ã³ããŒä»£å ¥ã®åïŒ
ã³ããŒä»£å ¥ã®åŸïŒ
èŠç¹ïŒ
-
C++ 㯠Rust ãšã¯å°ãç°ãªãéžæãããŠããŸãã
=ã¯ããŒã¿ãã³ããŒããããã æååããŒã¿ã¯ã¯ããŒã³ãããªããã°ãªããŸãããããã§ãªããšãã©ã¡ããã® æååãã¹ã³ãŒããæãããšãã«äºéè§£æŸãèµ·ããŠããŸããŸãã -
C++ ã«ã¯
std::moveããããããã¯å€ããã ãŒãããŠããããšã瀺ããã㫠䜿ãããŸããäŸãs2 = std::move(s1)ã ã£ãå ŽåãããŒãå²ãåœãŠã¯ çºçããŸãããã ãŒãåŸã®s1ã¯ãæå¹ã§ã¯ãããã®ã®æªèŠå®ã®ç¶æ ã« ãªããŸããRust ãšã¯ç°ãªããããã°ã©ãã¯s1ãåŒãç¶ã䜿çšã§ããŸãã -
Rust ãšç°ãªããC++ ã®
=ã¯ãã³ããŒãŸãã¯ã ãŒããããåã«ãã£ãŠæ±ºãŸã ä»»æã®ã³ãŒããå®è¡ã§ããŸãã
Clone
ãšãã«ã¯ãå€ã®ã³ããŒã äœããããªã ããšããããŸããClone ãã¬ã€ãã¯ãããå®çŸããŸãã
// Copyright 2023 Google LLC // SPDX-License-Identifier: Apache-2.0 fn say_hello(name: String) { println!("Hello {name}") } fn main() { let name = String::from("Alice"); say_hello(name.clone()); say_hello(name); }
-
Cloneã®èãæ¹ã¯ãããŒãå²ãåœãŠãã©ãã§çºçããŠããããèŠã€ããããããããšã§ãã.clone()ããvec!ãBox::newã®ãããªãã®ãæ¢ããŠãã ããã -
åçšãã§ãã«ãŒã®åé¡ã clone ã§åãæããããšã§æ»ã£ãŠããŠãããã® clone ãåãé€ãããæé©åã詊ã¿ãããšããã®ã¯ããããããšã§ãã
-
äžè¬ã«
cloneã¯å€ã®ãã£ãŒãã³ããŒãè¡ããŸããã€ãŸããããšãã°é åã clone ãããšããã®é åã®ãã¹ãŠã®èŠçŽ ãåæ§ã« clone ãããŸãã -
cloneã®æåã¯ãŠãŒã¶ãŒå®çŸ©ãªã®ã§ãå¿ èŠã§ããã°ã«ã¹ã¿ã ã®ã¯ããŒã³ããžãã¯ãå®è¡ã§ããŸãã
Copyå
ã ãŒãã»ãã³ãã£ã¯ã¹ãããã©ã«ãã§ãããç¹å®ã®åã¯ããã©ã«ãã§ã³ããŒãããŸãã
// Copyright 2023 Google LLC // SPDX-License-Identifier: Apache-2.0 fn main() { let x = 42; let y = x; dbg!(x); // Copy ã§ãªããã°ã¢ã¯ã»ã¹ã§ããªã dbg!(y); }
ãããã®å㯠Copy ãã¬ã€ããå®è£
ããŠããŸãã
èªåã§å®çŸ©ããåã§ããã³ããŒã»ãã³ãã£ã¯ã¹ã䜿ãããã«ãªããã€ã³ã§ããŸãã
// Copyright 2023 Google LLC // SPDX-License-Identifier: Apache-2.0 #[derive(Copy, Clone, Debug)] struct Point(i32, i32); fn main() { let p1 = Point(3, 4); let p2 = p1; println!("p1: {p1:?}"); println!("p2: {p2:?}"); }
- 代å
¥åŸã
p1ãšp2ã¯ã©ã¡ããããããã®ããŒã¿ãææããŸãã - ãŸãã
p1.clone()ã䜿ã£ãŠããŒã¿ãæç€ºçã«ã³ããŒããããšãã§ããŸãã
ã³ããŒãšã¯ããŒã³ã¯åããã®ã§ã¯ãããŸããã
- ã³ããŒã¯ã¡ã¢ãªé åã®ãããåäœã®è€è£œãæããä»»æã®ãªããžã§ã¯ãã«å¯ŸããŠæ©èœããããã§ã¯ãããŸããã
- ã³ããŒã§ã¯ã«ã¹ã¿ã ããžãã¯ãå ¥ããããŸããïŒC++ ã®ã³ããŒã³ã³ã¹ãã©ã¯ã¿ãšã¯ç°ãªããŸãïŒã
- ã¯ããŒã³ã¯ããäžè¬çãªæäœã§ããã
Cloneãã¬ã€ããå®è£ ããããšã§ã«ã¹ã¿ã ãªæ¯ãèããå¯èœã§ãã - ã³ããŒã¯
Dropãã¬ã€ããå®è£ ããŠããåã§ã¯æ©èœããŸããã
äžã®äŸã§ã次ã詊ããŠãã ããã
struct Pointã«Stringãã£ãŒã«ãã远å ããŸããStringã¯Copyåã§ã¯ãªããããã³ã³ãã€ã«ã§ããªããªããŸããderive屿§ããCopyãåé€ããŸãããããšãã³ã³ãã€ã©ãšã©ãŒã¯p1ã®println!ã§çºçããŸãã- 代ããã«
p1ãã¯ããŒã³ãããšåäœããããšã確èªããŸãã
ããã«è©³ãã
- å
񑆇
§ã¯
Copy/Cloneã§ãããå¯å€åç §ã¯ããã§ã¯ãããŸãããããã¯ãRust ãå¯å€åç §ã«æä»æ§ãèŠæ±ããããã§ãããããã£ãŠãå ±æåç §ã®ã³ããŒãäœãã®ã¯æå¹ã§ãããå¯å€åç §ã®ã³ããŒãäœããš Rust ã®åçšèŠåã«éåããŸãã
Drop ãã¬ã€ã
Drop ãå®è£
ããå€ã¯ãã¹ã³ãŒããæãããšãã«å®è¡ããã³ãŒããæå®ã§ããŸã:
// èäœæš© 2023 Google LLC // SPDX-License-Identifier: Apache-2.0 struct Droppable { name: &'static str, } impl Drop for Droppable { fn drop(&mut self) { println!("Dropping {}", self.name); } } fn main() { let a = Droppable { name: "a" }; { let b = Droppable { name: "b" }; { let c = Droppable { name: "c" }; let d = Droppable { name: "d" }; println!("Exiting innermost block"); } println!("Exiting next block"); } drop(a); println!("Exiting main"); }
std::mem::dropã¯std::ops::Drop::dropãšåãã§ã¯ãªãããšã«æ³šæããŠãã ããã- å€ã¯ã¹ã³ãŒããæãããšèªåçã«ãããããããŸãã
- å€ãããããããããšãããã®å€ã
std::ops::Dropãå®è£ ããŠããã°ããã®Drop::dropå®è£ ãåŒã³åºãããŸãã - ãã®åŸããã®ãã¹ãŠã®ãã£ãŒã«ãããããèªäœã
Dropãå®è£ ããŠãããã©ããã« ããããããããããããŸãã std::mem::dropã¯ãä»»æã®å€ãåãåãã ãã®ç©ºã®é¢æ°ã§ããéèŠãªã®ã¯ããã®å€ã® æææš©ãååŸããããšã§ãããã®ããããã®ã¹ã³ãŒãã®çµããã§å€ããããããããŸãã ããã«ãããæ¬æ¥ãªãã¹ã³ãŒããæãããŸã§æ®ãå€ããããæ©ãæ®µéã§æç€ºçã« ããããããããã®äŸ¿å©ãªæ¹æ³ã«ãªããŸãã- ããã¯ã
dropæã«äœããã®åŠçãè¡ããªããžã§ã¯ããããšãã°ããã¯ã®è§£æŸã ãã¡ã€ã«ãéããããšãªã©ã«åœ¹ç«ã¡ãŸãã
- ããã¯ã
è°è«ã®ãã€ã³ã:
- ãªã
Drop::dropã¯selfãåãåããªãã®ã§ããããïŒ- ç°¡åã«èšããšãããããã ãšãããšããããã¯ã®çµããã§
std::mem::dropã åŒã³åºããããã®çµæDrop::dropãããäžåºŠåŒã³åºãããŠã ã¹ã¿ãã¯ãªãŒããŒãããŒã«ãªããŸãïŒ
- ç°¡åã«èšããšãããããã ãšãããšããããã¯ã®çµããã§
drop(a)ãa.drop()ã«çœ®ãæããŠã¿ãŠãã ããã
æŒç¿: ãã«ããŒå
ãã®äŸã§ã¯ããã¹ãŠã®ããŒã¿ãææããè€éãªããŒã¿åãå®è£ ããŸãã æ°ããå€ã䟿å©ãªé¢æ°ã䜿ã£ãŠå°ããã€æ§ç¯ã§ããããã«ããããã«ãããã«ããŒãã¿ãŒã³ãã䜿çšããŸãã
æ¬ ããŠããéšåãåããŠãã ããã
// Copyright 2023 Google LLC // SPDX-License-Identifier: Apache-2.0 #[derive(Debug)] enum Language { Rust, Java, Perl, } #[derive(Clone, Debug)] struct Dependency { name: String, version_expression: String, } /// A representation of a software package. #[derive(Debug)] struct Package { name: String, version: String, authors: Vec<String>, dependencies: Vec<Dependency>, language: Option<Language>, } impl Package { /// Return a representation of this package as a dependency, for use in /// building other packages. fn as_dependency(&self) -> Dependency { todo!("1") } } /// A builder for a Package. Use `build()` to create the `Package` itself. struct PackageBuilder(Package); impl PackageBuilder { fn new(name: impl Into<String>) -> Self { todo!("2") } /// Set the package version. fn version(mut self, version: impl Into<String>) -> Self { self.0.version = version.into(); self } /// Set the package authors. fn authors(mut self, authors: Vec<String>) -> Self { todo!("3") } /// Add an additional dependency. fn dependency(mut self, dependency: Dependency) -> Self { todo!("4") } /// Set the language. If not set, language defaults to None. fn language(mut self, language: Language) -> Self { todo!("5") } fn build(self) -> Package { self.0 } } fn main() { let base64 = PackageBuilder::new("base64").version("0.13").build(); dbg!(&base64); let log = PackageBuilder::new("log").version("0.4").language(Language::Rust).build(); dbg!(&log); let serde = PackageBuilder::new("serde") .authors(vec!["djmitche".into()]) .version(String::from("4.0")) .dependency(base64.as_dependency()) .dependency(log.as_dependency()) .build(); dbg!(serde); }
è§£ç
// Copyright 2023 Google LLC // SPDX-License-Identifier: Apache-2.0 #[derive(Debug)] enum Language { Rust, Java, Perl, } #[derive(Clone, Debug)] struct Dependency { name: String, version_expression: String, } /// A representation of a software package. #[derive(Debug)] struct Package { name: String, version: String, authors: Vec<String>, dependencies: Vec<Dependency>, language: Option<Language>, } impl Package { /// Return a representation of this package as a dependency, for use in /// building other packages. fn as_dependency(&self) -> Dependency { Dependency { name: self.name.clone(), version_expression: self.version.clone(), } } } /// A builder for a Package. Use `build()` to create the `Package` itself. struct PackageBuilder(Package); impl PackageBuilder { fn new(name: impl Into<String>) -> Self { Self(Package { name: name.into(), version: "0.1".into(), authors: Vec::new(), dependencies: Vec::new(), language: None, }) } /// Set the package version. fn version(mut self, version: impl Into<String>) -> Self { self.0.version = version.into(); self } /// Set the package authors. fn authors(mut self, authors: Vec<String>) -> Self { self.0.authors = authors; self } /// Add an additional dependency. fn dependency(mut self, dependency: Dependency) -> Self { self.0.dependencies.push(dependency); self } /// Set the language. If not set, language defaults to None. fn language(mut self, language: Language) -> Self { self.0.language = Some(language); self } fn build(self) -> Package { self.0 } } fn main() { let base64 = PackageBuilder::new("base64").version("0.13").build(); dbg!(&base64); let log = PackageBuilder::new("log").version("0.4").language(Language::Rust).build(); dbg!(&log); let serde = PackageBuilder::new("serde") .authors(vec!["djmitche".into()]) .version(String::from("4.0")) .dependency(base64.as_dependency()) .dependency(log.as_dependency()) .build(); dbg!(serde); }
ã¹ããŒããã€ã³ã¿
segment outline
Box<T>
Box ã¯ãããŒãäžã®ããŒã¿ãæãææãã€ã³ã¿ ã§ã:
// Copyright 2023 Google LLC // SPDX-License-Identifier: Apache-2.0 fn main() { let five = Box::new(5); println!("five: {}", *five); }
Box<T> 㯠Deref<Target = T> ãå®è£
ããŠããããã T ã®ã¡ãœããã Box<T> ã«å¯ŸããŠçŽæ¥åŒã³åºããŸãã
ååž°çãªããŒã¿åãåçãªãµã€ãºãæã€ããŒã¿åã¯ããã€ã³ã¿ã«ãã鿥åç
§ãªãã§ã¯ ã€ã³ã©ã€ã³ã«æ ŒçŽã§ããŸãããBox ã¯ãã®éæ¥åç
§ãå®çŸããŸã:
// Copyright 2023 Google LLC // SPDX-License-Identifier: Apache-2.0 #[derive(Debug)] enum List<T> { /// 空ã§ãªããªã¹ã: æåã®èŠçŽ ãšæ®ãã®ãªã¹ãã Element(T, Box<List<T>>), /// 空ã®ãªã¹ãã Nil, } fn main() { let list: List<i32> = List::Element(1, Box::new(List::Element(2, Box::new(List::Nil)))); println!("{list:?}"); }
-
Box㯠C++ ã®std::unique_ptrã«äŒŒãŠããŸãããnull ã§ã¯ãªãããšã ä¿èšŒãããŠããŸãã -
次ã®ãããªå Žåã
Boxã圹ç«ã¡ãŸã:- ã³ã³ãã€ã«æã«ãµã€ãºãç¥ãããšãã§ããªãåãæ±ãããRust ã³ã³ãã€ã©ã¯ æ£ç¢ºãªãµã€ãºãç¥ãå¿ èŠãããå Žåã
- 倧éã®ããŒã¿ã®æææš©ãç§»åãããå Žåãã¹ã¿ãã¯äžã§å€§éã®ããŒã¿ãã³ããŒãã ããšãé¿ããããã代ããã«ããŒã¿ãããŒãäžã®
Boxã«æ ŒçŽãã ç§»åããã®ã¯ãã€ã³ã¿ã ãã«ããŸãã
-
Boxã䜿ãããListã®äžã«ListãçŽæ¥åã蟌ãããšãããšã ã³ã³ãã€ã©ã¯ã¡ã¢ãªäžã®ãã®åã®åºå®ãµã€ãºãèšç®ã§ããŸãã ïŒListã®ãµã€ãºãç¡éã«ãªã£ãŠããŸãããã§ãïŒã -
Boxã¯éåžžã®ãã€ã³ã¿ãšåããµã€ãºã§ããã ããŒãäžã®Listã®æ¬¡ã®èŠçŽ ãæãã ããªã®ã§ããã®åé¡ã解決ããŸãã -
Listã®å®çŸ©ããBoxãåãé€ããã³ã³ãã€ã©ãšã©ãŒã確èªããŠãã ããããããš ârecursive without indirectionâ ãšããã¡ãã»ãŒãžã衚瀺ãããŸããããã¯ãããŒã¿ã®ååž°ã§ã¯ å€ãçŽæ¥æ ŒçŽããã®ã§ã¯ãªããBoxãäœããã®åç §ã®ãããªéæ¥åç §ã䜿ã å¿ èŠãããããã§ãã -
Box㯠C++ ã®std::unique_ptrã«äŒŒãŠããŸããã空ã null ã«ã¯ã§ããŸããã ãã®ããBoxã¯ãã³ã³ãã€ã©ãäžéšã® enum ã®æ ŒçŽãæé©åã§ããåã® 1 ã€ã«ãªããŸãïŒâniche optimizationâïŒã
Rc
Rc ã¯åç
§ã«ãŠã³ãæ¹åŒã®å
±æãã€ã³ã¿ã§ããè€æ°ã®å ŽæããåãããŒã¿ãåç
§ ããå¿
èŠãããå Žåã«äœ¿çšããŸã:
// Copyright 2023 Google LLC // SPDX-License-Identifier: Apache-2.0 use std::rc::Rc; fn main() { let a = Rc::new(10); let b = Rc::clone(&a); dbg!(a); dbg!(b); }
å Rc ã¯ã匷åç
§ãšåŒ±åç
§ãããã³å€ãå«ãåãå
±æããŒã¿æ§é ã æããŸã:
- ãã«ãã¹ã¬ããã®ã³ã³ããã¹ãã§ã¯
ArcãšMutexãåç §ã㊠ãã ããã - å
±æãã€ã³ã¿ã
Weakãã€ã³ã¿ãž ããŠã³ã°ã¬ãŒã ããŠãé©åã« ããããããã埪ç°åç §ãäœæã§ããŸãã
Rcã®åç §ã«ãŠã³ãã«ãããåç §ãååšããéãå éšã®å€ãæå¹ã§ããããšã ä¿èšŒãããŸãã- Rust ã®
Rc㯠C++ ã®std::shared_ptrã®ãããªãã®ã§ãã Rc::cloneã¯äœã³ã¹ãã§ããåãã¢ãã±ãŒã·ã§ã³ãžã®ãã€ã³ã¿ãäœæãã åç §ã«ãŠã³ããå¢ãããŸãããã£ãŒãã¯ããŒã³ã¯è¡ããªããããéåžžã¯ã³ãŒãã® ããã©ãŒãã³ã¹åé¡ã調ã¹ãéã«ç¡èŠã§ããŸããmake_mutã¯å¿ èŠã«å¿ããŠå®éã«å éšã®å€ãã¯ããŒã³ãïŒâclone-on-writeâïŒã å¯å€åç §ãè¿ããŸãã- åç
§ã«ãŠã³ãã確èªããã«ã¯
Rc::strong_countã䜿çšããŸãã Rc::downgradeã䜿ããšãé©åã«ããããããã埪ç°åç §ãäœæãããã㮠匱ãåç §ã«ãŠã³ããæã€ ãªããžã§ã¯ããåŸãããŸãïŒå€ãã®å ŽåRefCellãš çµã¿åãããŠäœ¿çšããŸãïŒã
æææš©ãæã€ãã¬ã€ããªããžã§ã¯ã
åã«ããã¬ã€ããªããžã§ã¯ããåç
§ãšãšãã«äœ¿çšããæ¹æ³ãããšãã° &dyn Pet ãèŠãŸããã ããããBox ã®ãããªã¹ããŒããã€ã³ã¿ãšãã¬ã€ããªããžã§ã¯ããçµã¿åãããŠäœ¿çšãã æææš©ãæã€ãã¬ã€ããªããžã§ã¯ã Box<dyn Pet> ãäœãããšãã§ããŸãã
// èäœæš© 2024 Google LLC // SPDX-License-Identifier: Apache-2.0 struct Dog { name: String, age: i8, } struct Cat { lives: i8, } trait Pet { fn talk(&self) -> String; } impl Pet for Dog { fn talk(&self) -> String { format!("ã¯ã³ãç§ã®ååã¯{}ã§ãïŒ", self.name) } } impl Pet for Cat { fn talk(&self) -> String { String::from("ãã£ãŒïŒ") } } fn main() { let pets: Vec<Box<dyn Pet>> = vec![ Box::new(Cat { lives: 9 }), Box::new(Dog { name: String::from("Fido"), age: 5 }), ]; for pet in pets { println!("ããã«ã¡ã¯ãããªãã¯èª°ã§ããïŒ {}", pet.talk()); } }
pets ãå²ãåœãŠãåŸã®ã¡ã¢ãªã¬ã€ã¢ãŠã:
- ç¹å®ã®ãã¬ã€ããå®è£
ããåã¯ããããããµã€ãºãç°ãªãå ŽåããããŸããããã«ããã äžã®äŸã®
Vec<dyn Pet>ã®ãããªãã®ãæã€ããšã¯ã§ããŸããã dyn Petã¯ãPetãå®è£ ããåçãµã€ãºåã«ã€ããŠã³ã³ãã€ã©ã«äŒãã æ¹æ³ã§ãã- ãã®äŸã§ã¯ã
petsã¯ã¹ã¿ãã¯ã«å²ãåœãŠããããã¯ã¿ã®ããŒã¿ã¯ããŒãäžã« ãããŸãã2 ã€ã®ãã¯ã¿èŠçŽ ã¯ ãã¡ãããã€ã³ã¿ ã§ã:- ãã¡ãããã€ã³ã¿ã¯ãå¹
ã 2 åã®ãã€ã³ã¿ã§ããããã«ã¯ 2 ã€ã®æ§æèŠçŽ ã ãããŸããå®éã®ãªããžã§ã¯ããžã®ãã€ã³ã¿ãšããã®ç¹å®ã®ãªããžã§ã¯ãã«å¯Ÿãã
Petå®è£ ã® virtual method tableïŒvtableïŒãžã®ãã€ã³ã¿ã§ãã Fidoãšããååã®Dogã®ããŒã¿ã¯ãnameãã£ãŒã«ããšageãã£ãŒã«ãã§ããCatã«ã¯livesãã£ãŒã«ãããããŸãã
- ãã¡ãããã€ã³ã¿ã¯ãå¹
ã 2 åã®ãã€ã³ã¿ã§ããããã«ã¯ 2 ã€ã®æ§æèŠçŽ ã ãããŸããå®éã®ãªããžã§ã¯ããžã®ãã€ã³ã¿ãšããã®ç¹å®ã®ãªããžã§ã¯ãã«å¯Ÿãã
- äžã®äŸã§ã次ã®åºåãæ¯èŒããŠãã ãã:
// èäœæš© 2024 Google LLC // SPDX-License-Identifier: Apache-2.0 println!("{} {}", std::mem::size_of::<Dog>(), std::mem::size_of::<Cat>()); println!("{} {}", std::mem::size_of::<&Dog>(), std::mem::size_of::<&Cat>()); println!("{}", std::mem::size_of::<&dyn Pet>()); println!("{}", std::mem::size_of::<Box<dyn Pet>>());
æŒç¿: äºåæš
äºåæšã¯ããã¹ãŠã®ããŒãã 2 ã€ã®åããŒãïŒå·Šãšå³ïŒãæã€æšæ§é ã® ããŒã¿æ§é ã§ããåããŒããå€ãæ ŒçŽããæšãäœæããŸããããããŒã N ã«ã€ããŠãN ã®å·Šéšåæšã«ãããã¹ãŠã®ããŒãã¯ããå°ããå€ãå«ã¿ãN ã®å³éšåæšã«ãããã¹ãŠã®ããŒãã¯ãã倧ããå€ãå«ã¿ãŸããããå€ã¯æšã« 1 åã ãæ ŒçŽããããã®ãšããŸããã€ãŸããéè€ããããŒãã¯ãããŸããã
次ã®åãå®è£ ããŠãäžãããããã¹ããéãããã«ããŠãã ããã
// Copyright 2023 Google LLC // SPDX-License-Identifier: Apache-2.0 /// A node in the binary tree. #[derive(Debug)] struct Node<T: Ord> { value: T, left: Subtree<T>, right: Subtree<T>, } /// A possibly-empty subtree. #[derive(Debug)] struct Subtree<T: Ord>(Option<Box<Node<T>>>); /// A container storing a set of values, using a binary tree. /// /// If the same value is added multiple times, it is only stored once. #[derive(Debug)] pub struct BinaryTree<T: Ord> { root: Subtree<T>, } impl<T: Ord> BinaryTree<T> { fn new() -> Self { Self { root: Subtree::new() } } fn insert(&mut self, value: T) { self.root.insert(value); } fn has(&self, value: &T) -> bool { self.root.has(value) } fn len(&self) -> usize { self.root.len() } } // `Node` ã® `new` ãå®è£ ããŠãã ããã // `Subtree` ã® `new`ã`insert`ã`len`ã`has` ãå®è£ ããŠãã ããã #[cfg(test)] mod tests { use super::*; #[test] fn len() { let mut tree = BinaryTree::new(); assert_eq!(tree.len(), 0); tree.insert(2); assert_eq!(tree.len(), 1); tree.insert(1); assert_eq!(tree.len(), 2); tree.insert(2); // not a unique item assert_eq!(tree.len(), 2); tree.insert(3); assert_eq!(tree.len(), 3); } #[test] fn has() { let mut tree = BinaryTree::new(); fn check_has(tree: &BinaryTree<i32>, exp: &[bool]) { let got: Vec<bool> = (0..exp.len()).map(|i| tree.has(&(i as i32))).collect(); assert_eq!(&got, exp); } check_has(&tree, &[false, false, false, false, false]); tree.insert(0); check_has(&tree, &[true, false, false, false, false]); tree.insert(4); check_has(&tree, &[true, false, false, false, true]); tree.insert(4); check_has(&tree, &[true, false, false, false, true]); tree.insert(3); check_has(&tree, &[true, false, false, true, true]); } #[test] fn unbalanced() { let mut tree = BinaryTree::new(); for i in 0..100 { tree.insert(i); } assert_eq!(tree.len(), 100); assert!(tree.has(&50)); } }
è§£ç
// Copyright 2023 Google LLC // SPDX-License-Identifier: Apache-2.0 use std::cmp::Ordering; /// A node in the binary tree. #[derive(Debug)] struct Node<T: Ord> { value: T, left: Subtree<T>, right: Subtree<T>, } /// A possibly-empty subtree. #[derive(Debug)] struct Subtree<T: Ord>(Option<Box<Node<T>>>); /// A container storing a set of values, using a binary tree. /// /// If the same value is added multiple times, it is only stored once. #[derive(Debug)] pub struct BinaryTree<T: Ord> { root: Subtree<T>, } impl<T: Ord> BinaryTree<T> { fn new() -> Self { Self { root: Subtree::new() } } fn insert(&mut self, value: T) { self.root.insert(value); } fn has(&self, value: &T) -> bool { self.root.has(value) } fn len(&self) -> usize { self.root.len() } } impl<T: Ord> Subtree<T> { fn new() -> Self { Self(None) } fn insert(&mut self, value: T) { match &mut self.0 { None => self.0 = Some(Box::new(Node::new(value))), Some(n) => match value.cmp(&n.value) { Ordering::Less => n.left.insert(value), Ordering::Equal => {} Ordering::Greater => n.right.insert(value), }, } } fn has(&self, value: &T) -> bool { match &self.0 { None => false, Some(n) => match value.cmp(&n.value) { Ordering::Less => n.left.has(value), Ordering::Equal => true, Ordering::Greater => n.right.has(value), }, } } fn len(&self) -> usize { match &self.0 { None => 0, Some(n) => 1 + n.left.len() + n.right.len(), } } } impl<T: Ord> Node<T> { fn new(value: T) -> Self { Self { value, left: Subtree::new(), right: Subtree::new() } } } #[cfg(test)] mod tests { use super::*; #[test] fn len() { let mut tree = BinaryTree::new(); assert_eq!(tree.len(), 0); tree.insert(2); assert_eq!(tree.len(), 1); tree.insert(1); assert_eq!(tree.len(), 2); tree.insert(2); // not a unique item assert_eq!(tree.len(), 2); tree.insert(3); assert_eq!(tree.len(), 3); } #[test] fn has() { let mut tree = BinaryTree::new(); fn check_has(tree: &BinaryTree<i32>, exp: &[bool]) { let got: Vec<bool> = (0..exp.len()).map(|i| tree.has(&(i as i32))).collect(); assert_eq!(&got, exp); } check_has(&tree, &[false, false, false, false, false]); tree.insert(0); check_has(&tree, &[true, false, false, false, false]); tree.insert(4); check_has(&tree, &[true, false, false, false, true]); tree.insert(4); check_has(&tree, &[true, false, false, false, true]); tree.insert(3); check_has(&tree, &[true, false, false, true, true]); } #[test] fn unbalanced() { let mut tree = BinaryTree::new(); for i in 0..100 { tree.insert(i); } assert_eq!(tree.len(), 100); assert!(tree.has(&50)); } }
ãåž°ããªãã
session outline
åçš
segment outline
å€ã®åçš
åã«èŠãããã«ã颿°ãåŒã³åºããšãã«æææš©ãç§»åãã代ããã«ã 颿°ã«ãã®å€ã åçš ãããããšãã§ããŸãïŒ
// èäœæš© 2023 Google LLC // SPDX-License-Identifier: Apache-2.0 #[derive(Debug)] struct Point(i32, i32); fn add(p1: &Point, p2: &Point) -> Point { Point(p1.0 + p2.0, p1.1 + p2.1) } fn main() { let p1 = Point(3, 4); let p2 = Point(10, 20); let p3 = add(&p1, &p2); println!("{p1:?} + {p2:?} = {p3:?}"); }
add颿°ã¯ 2 ã€ã®ãã€ã³ãã åçš ããæ°ãããã€ã³ããè¿ããŸãã- åŒã³åºãå ã¯å ¥åã®æææš©ãä¿æããŸãã
ãã®ã¹ã©ã€ã㯠1 æ¥ç®ã®åç §ã«é¢ããå 容ã®åŸ©ç¿ã§ããã 颿°åŒæ°ãšæ»ãå€ãå°ãå«ããããã«å 容ãåºããŠããŸãã
ããã«èª¿ã¹ãããš
ã¹ã¿ãã¯äžã§ã®æ»ãå€ãšã€ã³ã©ã€ã³åã«é¢ããã¡ã¢ïŒ
-
addããã®å€ã®è¿åŽãäœã³ã¹ãã§ããããšã瀺ããŠãã ãããããã¯ãã³ã³ãã€ã©ã add ã®åŒã³åºãã main ã«ã€ã³ã©ã€ã³åããããšã§ã³ããŒæäœãåé€ã§ããããã§ããäžã® ã³ãŒããã¹ã¿ãã¯ã¢ãã¬ã¹ã衚瀺ããããã«å€æŽããPlayground ã§å®è¡ãããã Godbolt ã§ã¢ã»ã³ããªãèŠãŠãã ãããâDEBUGâ æé©åã¬ãã«ã§ã¯ã¢ãã¬ã¹ã¯å€ããã¯ãã§ãããâRELEASEâ èšå®ã«å€æŽãããš åããŸãŸã§ãïŒ// èäœæš© 2023 Google LLC // SPDX-License-Identifier: Apache-2.0 #[derive(Debug)] struct Point(i32, i32); fn add(p1: &Point, p2: &Point) -> Point { let p = Point(p1.0 + p2.0, p1.1 + p2.1); println!("&p.0: {:p}", &p.0); p } pub fn main() { let p1 = Point(3, 4); let p2 = Point(10, 20); let p3 = add(&p1, &p2); println!("&p3.0: {:p}", &p3.0); println!("{p1:?} + {p2:?} = {p3:?}"); } -
Rust ã³ã³ãã€ã©ã¯èªåã€ã³ã©ã€ã³åãè¡ããŸããããã¯é¢æ°åäœã§
#[inline(never)]ã䜿ã£ãŠç¡å¹ã«ã§ããŸãã -
ãã£ããç¡å¹ã«ãããšã衚瀺ãããã¢ãã¬ã¹ã¯ãã¹ãŠã®æé©åã¬ãã«ã§ å€ãããŸããGodbolt ã Playground ãèŠããšããã®å Žåã®å€ã®è¿åŽã¯ ABI ã«äŸåããããšãããããŸããããšãã° amd64 ã§ã¯ããã€ã³ããæ§æãã 2 ã€ã® i32 㯠2 ã€ã®ã¬ãžã¹ã¿ïŒeax ãš edxïŒã§è¿ãããŸãã
åçšãã§ãã¯
Rust ã® åçšãã§ãã«ãŒ ã¯ãå€ãåçšããæ¹æ³ã«å¶çŽã課ããŸãã åç §ãããããåçšããŠããå€ã è¶ ããŠçåãã ããšã¯ã§ããªãããšã¯ããã§ã«èŠãŸããã
// Copyright 2023 Google LLC // SPDX-License-Identifier: Apache-2.0 fn main() { let x_ref = { let x = 10; &x }; dbg!(x_ref); }
åçšãã§ãã«ãŒã匷å¶ããããã 1 ã€ã®äž»èŠãªã«ãŒã«ããããŸãããšã€ãªã¢ã·ã³ã° ã«ãŒã«ã§ããããå€ã«ã€ããŠã¯ãã©ã®æç¹ã§ã次ã®ããããäžæ¹ã®ã¿ãæãç«ã¡ãŸãã
- ãã®å€ãžã®å ±æåç §ã 1 ã€ä»¥äžæã€ããšãã§ããããŸãã¯
- ãã®å€ãžã®æä»çåç §ãã¡ããã© 1 ã€ã ãæã€ããšãã§ããŸãã
// Copyright 2023 Google LLC // SPDX-License-Identifier: Apache-2.0 fn main() { let mut a = 10; let b = &a; { let c = &mut a; *c = 20; } dbg!(a); dbg!(b); }
- ãoutlivesãã«ãŒã«ã¯ãæåã«åç §ãèŠããšãã«ãã§ã«ç€ºããŸãããããã§ æ¹ããŠåãäžããã®ã¯ãåçšãã§ãã¯ãåçšãæ€èšŒããããã«ããã€ãç°ãªã ã«ãŒã«ã«åŸã£ãŠããããšãåè¬è ã«ç€ºãããã§ãã
- äžã®ã³ãŒããã³ã³ãã€ã«ã§ããªãã®ã¯ã
aãåæã«å¯å€ãšããŠïŒcãéããŠïŒ åçšãããäžå€ãšããŠïŒbãéããŠïŒåçšãããŠããããã§ãã- èŠä»¶ã¯ãç«¶åããåç
§ãåãæç¹ã« ååšããªã ããšã ãšããç¹ã«æ³šæã㊠ãã ãããåç
§ãã©ãã§ããªãã¡ã¬ã³ã¹ããããã¯é¢ä¿ãããŸããã
*c = 20ãã³ã¡ã³ãã¢ãŠãããŠãcãäžåºŠã䜿ããªããŠãã³ã³ãã€ã©ãšã©ãŒã äŸç¶ãšããŠçºçããããšã瀺ããŠãã ããã - åçšã®ç«¶åãçºçãããã®ã«ãäžéã®åç
§
cã¯å¿ é ã§ã¯ãªãç¹ã«ã泚æã㊠ãã ãããcãaãžã®çŽæ¥ã®å€æŽã«çœ®ãæããããã§ãåæ§ã®ãšã©ãŒã çºçããããšã瀺ããŠãã ãããããã¯ãå€ãçŽæ¥å€æŽãããšå®è³ªçã«äžæç㪠å¯å€åç §ãäœãããããã§ãã
- èŠä»¶ã¯ãç«¶åããåç
§ãåãæç¹ã« ååšããªã ããšã ãšããç¹ã«æ³šæã㊠ãã ãããåç
§ãã©ãã§ããªãã¡ã¬ã³ã¹ããããã¯é¢ä¿ãããŸããã
- ã³ãŒããã³ã³ãã€ã«ã§ããããã«ããã«ã¯ã
bã®dbg!æãcãå°å ¥ãã ã¹ã³ãŒãããåã«ç§»åããŠãã ããã- ãã®å€æŽãè¡ããšãã³ã³ãã€ã©ã¯
bãcãéããaã®æ°ããå¯å€åçšãã åã§ãã䜿ãããªãããšãèªèããŸããããã¯åçšãã§ãã«ãŒã® ãéåå¥çã©ã€ãã¿ã€ã ããšåŒã°ããæ©èœã§ãã
- ãã®å€æŽãè¡ããšãã³ã³ãã€ã©ã¯
ããã«è©³ãã
- å³å¯ã«ã¯ãããããŒã¿ã«å¯Ÿããè€æ°ã®å¯å€åç §ã¯ãååçšã«ãã£ãŠåæã«ååš ã§ããŸããããã«ãããå ã®åç §ãç¡å¹ã«ããããšãªããå¯å€åç §ã颿°ã«æž¡ã ããšãã§ããŸãããã® Playground ã®äŸ ã¯ãã®æåã瀺ããŠããŸãã
- Rust ã¯ãæä»çåç §ã®å¶çŽã䜿ã£ãŠããã«ãã¹ã¬ããã³ãŒãã§ããŒã¿ç«¶åãçºç ããªãããšãä¿èšŒããŸããããã¯ãäžåºŠã« 1 ã€ã®ã¹ã¬ããããããŒã¿ã®äžéšã« å¯å€ã¢ã¯ã»ã¹ã§ããªãããã§ãã
- Rust ã¯ãã®å¶çŽãã³ãŒãã®æé©åã«ãå©çšããŸããããšãã°ãå ±æåç §ãæãå€ã¯ã ãã®åç §ã®ã©ã€ãã¿ã€ã ã®éãå®å šã«ã¬ãžã¹ã¿ã«ãã£ãã·ã¥ã§ããŸãã
- æ§é äœã®ãã£ãŒã«ãã¯äºãã«ç¬ç«ããŠåçšã§ããŸãããæ§é äœã®ã¡ãœããã åŒã³åºããšæ§é äœå šäœãåçšãããåã ã®ãã£ãŒã«ããžã®åç §ãç¡å¹ã«ãªãå¯èœæ§ã ãããŸãããã® Playground ã¹ãããã ã«ãã®äŸããããŸãã
åçšãšã©ãŒ
ãããã®åçšã«ãŒã«ãã©ã®ããã«ã¡ã¢ãªãšã©ãŒãé²ãã®ãã瀺ãå ·äœäŸãšããŠããã®èŠçŽ ãžã®åç §ãããç¶æ ã§ã³ã¬ã¯ã·ã§ã³ã倿Žããã±ãŒã¹ãèããŠã¿ãŸããã:
// èäœæš© 2024 Google LLC // SPDX-License-Identifier: Apache-2.0 fn main() { let mut vec = vec![1, 2, 3, 4, 5]; let elem = &vec[2]; vec.push(6); dbg!(elem); }
åæ§ã«ãã€ãã¬ãŒã¿ã®ç¡å¹åã®ã±ãŒã¹ãèããŠã¿ãŸããã:
// èäœæš© 2024 Google LLC // SPDX-License-Identifier: Apache-2.0 fn main() { let mut vec = vec![1, 2, 3, 4, 5]; for elem in &vec { vec.push(elem * 2); } }
- ã©ã¡ãã®ã±ãŒã¹ã§ããã³ã¬ã¯ã·ã§ã³ã«æ°ããèŠçŽ ã push ããŠå€æŽãããšãã³ã¬ã¯ã·ã§ã³ãåå²ãåœãŠãè¡ãå¿ èŠãããå Žåãã³ã¬ã¯ã·ã§ã³ã®èŠçŽ ãžã®æ¢åã®åç §ãç¡å¹ã«ãªãå¯èœæ§ããããŸãã
å éšå¯å€æ§
ç¶æ³ã«ãã£ãŠã¯ãå ±æïŒèªã¿åãå°çšïŒåç §ã®èåŸã«ããããŒã¿ã倿Žããå¿ èŠããããŸããããšãã°ãå ±æããŒã¿æ§é ãå éšãã£ãã·ã¥ãæã£ãŠããŠãèªã¿åãå°çšã¡ãœãããããã®ãã£ãã·ã¥ãæŽæ°ãããå ŽåããããŸãã
ãinterior mutabilityããã¿ãŒã³ã§ã¯ãå ±æåç §ã®èåŸã§æä»çïŒå¯å€ïŒã¢ã¯ã»ã¹ãå¯èœã«ããŸããæšæºã©ã€ãã©ãªã«ã¯ãããå®çŸããæ¹æ³ãããã€ãçšæãããŠãããããããéåžžã¯å®è¡æãã§ãã¯ãè¡ãããšã§å®å šæ§ã確ä¿ããŠããŸãã
ãã®ã¹ã©ã€ãã§æãéèŠãªãã€ã³ãã¯ãRust ãå ±æåç §ã®èåŸã«ããããŒã¿ã倿Žããããã® å®å šãª æ¹æ³ãæäŸããŠãããšããããšã§ãããã®å®å šæ§ã確ä¿ããæ¹æ³ã«ã¯ããŸããŸãªãã®ããããæ¬¡ã®ãµãã¹ã©ã€ãã§ãã®ããã€ãã玹ä»ããŸãã
Cell
Cell ã¯å€ãã©ããããCell ãžã®å
񑆇
§ã ãã䜿ã£ãŠãã®å€ãååŸãŸãã¯èšå®ã§ããããã«ããŸãããã ããå
éšã®å€ãžã®åç
§ã¯äžåèš±å¯ããŸãããåç
§ãååšããªããããåçšèŠåãç Žãããããšã¯ãããŸããã
// Copyright 2025 Google LLC // SPDX-License-Identifier: Apache-2.0 use std::cell::Cell; fn main() { // `cell` ã¯å¯å€ãšããŠå®£èšãããŠããªãããšã«æ³šæããŠãã ããã let cell = Cell::new(5); cell.set(123); dbg!(cell.get()); }
Cellã¯å®å šæ§ã確ä¿ããããã®ã·ã³ãã«ãªææ®µã§ãã&selfãåãåãsetã¡ãœãããæã£ãŠããŸããããã«ã¯å®è¡æãã§ãã¯ã¯äžèŠã§ãããå€ãã ãŒãããå¿ èŠãããããã®ããšèªäœã«ã³ã¹ãããããå ŽåããããŸãã
RefCell
RefCell ã¯ãå®éã«ã¯ Rust ã®åç
§ã§ã¯ãªã &T/&mut T ããšãã¥ã¬ãŒããã代æ¿å Ref ãš RefMut ãæäŸããããšã§ãã©ãããããå€ãžã®ã¢ã¯ã»ã¹ãšå€æŽãå¯èœã«ããŸãã
ãããã®åã¯ãRefCell å
ã®ã«ãŠã³ã¿ãŒã䜿ã£ãŠåçãã§ãã¯ãè¡ããå¥ã® Ref/RefMut ãšåæã« RefMut ãååšããªãããã«ããŸãã
DerefïŒRefMut ã«ã€ããŠã¯ DerefMut ãïŒãå®è£
ããããšã§ããããã®åã¯åç
§ãå€ãžéããããšãªããå
éšã®å€ã«å¯ŸããŠã¡ãœãããåŒã³åºããŸãã
// Copyright 2025 Google LLC // SPDX-License-Identifier: Apache-2.0 use std::cell::RefCell; fn main() { // `cell` ã¯å¯å€ãšããŠå®£èšãããŠããªãããšã«æ³šæããŠãã ããã let cell = RefCell::new(5); { let mut cell_ref = cell.borrow_mut(); *cell_ref = 123; // ããã¯å®è¡æãšã©ãŒãåŒãèµ·ãããŸãã // let other = cell.borrow(); // println!("{}", other); } println!("{cell:?}"); }
-
RefCellã¯ãRust ã®éåžžã®åçšèŠåïŒè€æ°ã®å ±æåç §ããŸã㯠1 ã€ã®æä»çåç §ã®ããããïŒãã©ã³ã¿ã€ã ãã§ãã¯ã§åŒ·å¶ããŸãããã®å Žåããã¹ãŠã®åçšã¯éåžžã«çããäºãã«éãªããªãããããã§ãã¯ã¯åžžã«æåããŸãã -
ãã®äŸã®è¿œå ã®ãããã¯ã¯ãã»ã«ã衚瀺ããåã«ã
borrow_mutã®åŒã³åºãã§äœãããåçšãçµäºãããããã®ãã®ã§ããåçšäžã®RefCellã衚瀺ããããšãããšã"{borrowed}"ãšããã¡ãã»ãŒãžã衚瀺ãããã ãã§ãã
ããã«èª¿ã¹ã
ååäœ¿çšæã®åæåãå¯èœã«ãã OnceCell ãš OnceLock ããããŸããããããæå¹ã«æŽ»çšããã«ã¯ãçŸæç¹ã®åè¬è
ããŸã æã£ãŠããªããããå°ãå€ãã®ç¥èãå¿
èŠã§ãã
æŒç¿: éæ³äœ¿ãã®ã€ã³ãã³ããª
ãã®æŒç¿ã§ã¯ãåçšãšæææš©ã«ã€ããŠåŠãã ããšã䜿ã£ãŠãéæ³äœ¿ãã®ã€ã³ãã³ããªã管çããŸãã
-
éæ³äœ¿ãã¯åªæã®ã³ã¬ã¯ã·ã§ã³ãæã£ãŠããŸããã€ã³ãã³ããªã«åªæã远å ãã颿°ãšããã®äžã®åªæãå±ãã颿°ãå®è£ ããå¿ èŠããããŸãã
-
åªæã«ã¯äœ¿çšåæ°ã®äžéããããŸããåªæã®æ®ã䜿çšåæ°ããªããªã£ããããããéæ³äœ¿ãã®ã€ã³ãã³ããªããåé€ããªããã°ãªããŸããã
// Copyright 2023 Google LLC // SPDX-License-Identifier: Apache-2.0 struct Spell { name: String, cost: u32, uses: u32, } struct Wizard { spells: Vec<Spell>, mana: u32, } impl Wizard { fn new(mana: u32) -> Self { Wizard { spells: vec![], mana } } // TODO: `add_spell` ãå®è£ ããŠãåªæã®æææš©ãåãåããããã // éæ³äœ¿ãã®ã€ã³ãã³ããªã«è¿œå ããã fn add_spell(..., spell: ...) { todo!() } // TODO: ã€ã³ãã³ããªããåªæãåçšããŠå±ããããã« // `cast_spell` ãå®è£ ãããéæ³äœ¿ãã®ããã¯åªæã®ã³ã¹ãåã ãæžãã // åªæã®äœ¿çšåæ°ã¯ 1 æžå°ããã¹ãã§ãã // // éæ³äœ¿ãã®ãããè¶³ããªãå Žåãåªæã¯å€±æããã¹ãã§ãã // åªæã®æ®ã䜿çšåæ°ããªãå Žåã¯ãã€ã³ãã³ããªããåé€ãããŸãã fn cast_spell(..., name: ...) { todo!() } } fn main() { let mut merlin = Wizard::new(100); let fireball = Spell { name: String::from("Fireball"), cost: 10, uses: 2 }; let ice_blast = Spell { name: String::from("Ice Blast"), cost: 15, uses: 1 }; merlin.add_spell(fireball); merlin.add_spell(ice_blast); merlin.cast_spell("Fireball"); // Casts successfully merlin.cast_spell("Ice Blast"); // Casts successfully, then removed merlin.cast_spell("Ice Blast"); // Fails (not found) merlin.cast_spell("Fireball"); // Casts successfully, then removed merlin.cast_spell("Fireball"); // Fails (not found) } #[cfg(test)] mod tests { use super::*; #[test] fn test_add_spell() { let mut wizard = Wizard::new(10); let spell = Spell { name: String::from("Fireball"), cost: 5, uses: 3 }; wizard.add_spell(spell); assert_eq!(wizard.spells.len(), 1); } #[test] fn test_cast_spell() { let mut wizard = Wizard::new(10); let spell = Spell { name: String::from("Fireball"), cost: 5, uses: 3 }; wizard.add_spell(spell); wizard.cast_spell("Fireball"); assert_eq!(wizard.mana, 5); assert_eq!(wizard.spells.len(), 1); assert_eq!(wizard.spells[0].uses, 2); } #[test] fn test_cast_spell_insufficient_mana() { let mut wizard = Wizard::new(10); let spell = Spell { name: String::from("Fireball"), cost: 15, uses: 3 }; wizard.add_spell(spell); wizard.cast_spell("Fireball"); assert_eq!(wizard.mana, 10); assert_eq!(wizard.spells.len(), 1); assert_eq!(wizard.spells[0].uses, 3); } #[test] fn test_cast_spell_not_found() { let mut wizard = Wizard::new(10); wizard.cast_spell("Fireball"); assert_eq!(wizard.mana, 10); } #[test] fn test_cast_spell_removal() { let mut wizard = Wizard::new(10); let spell = Spell { name: String::from("Fireball"), cost: 5, uses: 1 }; wizard.add_spell(spell); wizard.cast_spell("Fireball"); assert_eq!(wizard.mana, 5); assert_eq!(wizard.spells.len(), 0); } }
- ãã®æŒç¿ã®ç®æšã¯ãæææš©ãšåçšã®äžæ žæŠå¿µãç¹ã«ã³ã¬ã¯ã·ã§ã³ã®èŠçŽ ã® 1 ã€ãžã®åç §ãä¿æããŠããéã¯ãã®ã³ã¬ã¯ã·ã§ã³ã倿Žã§ããªããšããã«ãŒã«ãç·Žç¿ããããšã§ãã
add_spellã¯Spellã®æææš©ãåãåãããããWizardã®ã€ã³ãã³ããªãžã ãŒãããã¹ãã§ããcast_spellã¯ãã®æŒç¿ã®äžæ žã§ããããã«ã¯æ¬¡ãå¿ èŠã§ã:- åªæãèŠã€ããïŒã€ã³ããã¯ã¹ãŸãã¯åç §ã§ïŒã
- ããã確èªããŠæžããã
- åªæã®
usesãæžããã uses == 0ã®å Žåã¯åªæãåé€ããã
- åçšãã§ãã«ãŒã®ç«¶å: åŠç¿è
ãåªæãžã®åç
§ïŒäŸ:
let spell = &mut self.spells[i]ïŒãä¿æãããŸãŸããã®åç §ãåãã¹ã³ãŒãå ã§ãŸã ãçããŠãããéã«self.spells.remove(i)ãåŒã³åºãããšãããšãåçšãã§ãã«ãŒããšã©ãŒãå ±åããŸããããã¯ãåçšãã§ãã«ãŒãæºããããã«ã³ãŒããæ§æããæ¹æ³ïŒããšãã°ã€ã³ããã¯ã¹ã䜿ãããŸãã¯å€æŽã®åã«åçšãçµããããã«ããããšïŒã瀺ãçµ¶å¥œã®æ©äŒã§ãã
è§£ç: éæ³äœ¿ãã®æã¡ç©
// èäœæš© 2023 Google LLC // SPDX-License-Identifier: Apache-2.0 struct Spell { name: String, cost: u32, uses: u32, } struct Wizard { spells: Vec<Spell>, mana: u32, } impl Wizard { fn new(mana: u32) -> Self { Wizard { spells: vec![], mana } } fn add_spell(&mut self, spell: Spell) { self.spells.push(spell); } fn cast_spell(&mut self, name: &str) { let mut spell_idx = None; for idx in 0..self.spells.len() { if self.spells[idx].name == name { spell_idx = Some(idx); break; } } let Some(idx) = spell_idx else { println!("Spell {} not found!", name); return; }; let spell = &mut self.spells[idx]; if self.mana >= spell.cost { self.mana -= spell.cost; spell.uses -= 1; println!( "Casting {}! Mana left: {}. Uses left: {}", spell.name, self.mana, spell.uses ); if spell.uses == 0 { self.spells.remove(idx); } } else { println!("Not enough mana to cast {}!", spell.name); } } } fn main() { let mut merlin = Wizard::new(100); let fireball = Spell { name: String::from("Fireball"), cost: 10, uses: 2 }; let ice_blast = Spell { name: String::from("Ice Blast"), cost: 15, uses: 1 }; merlin.add_spell(fireball); merlin.add_spell(ice_blast); merlin.cast_spell("Fireball"); // Casts successfully merlin.cast_spell("Ice Blast"); // Casts successfully, then removed merlin.cast_spell("Ice Blast"); // Fails (not found) merlin.cast_spell("Fireball"); // Casts successfully, then removed merlin.cast_spell("Fireball"); // Fails (not found) } #[cfg(test)] mod tests { use super::*; #[test] fn test_add_spell() { let mut wizard = Wizard::new(10); let spell = Spell { name: String::from("Fireball"), cost: 5, uses: 3 }; wizard.add_spell(spell); assert_eq!(wizard.spells.len(), 1); } #[test] fn test_cast_spell() { let mut wizard = Wizard::new(10); let spell = Spell { name: String::from("Fireball"), cost: 5, uses: 3 }; wizard.add_spell(spell); wizard.cast_spell("Fireball"); assert_eq!(wizard.mana, 5); assert_eq!(wizard.spells.len(), 1); assert_eq!(wizard.spells[0].uses, 2); } #[test] fn test_cast_spell_insufficient_mana() { let mut wizard = Wizard::new(10); let spell = Spell { name: String::from("Fireball"), cost: 15, uses: 3 }; wizard.add_spell(spell); wizard.cast_spell("Fireball"); assert_eq!(wizard.mana, 10); assert_eq!(wizard.spells.len(), 1); assert_eq!(wizard.spells[0].uses, 3); } #[test] fn test_cast_spell_not_found() { let mut wizard = Wizard::new(10); wizard.cast_spell("Fireball"); assert_eq!(wizard.mana, 10); } #[test] fn test_cast_spell_removal() { let mut wizard = Wizard::new(10); let spell = Spell { name: String::from("Fireball"), cost: 5, uses: 1 }; wizard.add_spell(spell); wizard.cast_spell("Fireball"); assert_eq!(wizard.mana, 5); assert_eq!(wizard.spells.len(), 0); } }
ã©ã€ãã¿ã€ã
segment outline
颿°ã§ã®åçš
åçšãã§ãã¯ã®äžç°ãšããŠãã³ã³ãã€ã©ã¯åçšã颿°ã«ã©ã®ããã«æµå ¥ãã ã©ã®ããã«æµåºããããæšè«ããå¿ èŠããããŸããæãåçŽãªå Žåãåçšã¯ 颿°åŒã³åºãã®éã ãåç¶ããŸã:
// Copyright 2025 Google LLC // SPDX-License-Identifier: Apache-2.0 fn borrows(x: &i32) { dbg!(x); } fn main() { let mut val = 123; // 颿°åŒã³åºãã®ããã« `val` ãåçšããã borrows(&val); // åçšã¯çµäºããèªç±ã«å€æŽã§ããã val += 5; }
- ãã®äŸã§ã¯ã
borrowsã®åŒã³åºãã®ããã«valãåçšããŠããŸããããã«ããvalã倿Žããèœåã¯å¶éãããŸããã颿°åŒã³åºããæ»ããšåçšã¯çµäºãã åã³èªç±ã«å€æŽã§ããŸãã
åçšãè¿ã
ãããã颿°ã«åç §ãè¿ãããããšãã§ããŸãïŒããã¯ãåçšã颿°ããåŒã³åºãå ãžæ»ã£ãŠããããšãæå³ããŸã:
// Copyright 2025 Google LLC // SPDX-License-Identifier: Apache-2.0 fn identity(x: &i32) -> &i32 { x } fn main() { let mut x = 123; let out = identity(&x); // x = 5; // ð ïžâ `x` ã¯ãŸã åçšãããŠããŸãïŒ dbg!(out); }
-
Rust ã®é¢æ°ã¯åç §ãè¿ãããšãã§ããããã¯åçšã颿°ããåŒã³åºãå ãžæ»ã£ãŠããããšãæå³ããŸãã
-
颿°ãåç §ïŒãŸãã¯å¥ã®çš®é¡ã®åçšïŒãè¿ãå Žåãããã¯ãããããã®åŒæ°ã® 1 ã€ã«ç±æ¥ããŸããããã¯ããã®é¢æ°ã®æ»ãå€ã«ãã£ãŠã1 ã€ä»¥äžã®åŒæ°ã®åçšæéãå»¶é·ãããããšãæå³ããŸãã
-
ãã®ã±ãŒã¹ã¯ã颿°ã«æž¡ãããåçšã 1 ã€ã ããªã®ã§ãè¿ãããåçšãåããã®ã«éããããŸã æ¯èŒçåçŽã§ãã
è€æ°ã®åçš
ã§ã¯ãè€æ°ã®åçšã颿°ã«æž¡ããããã®ãã¡ 1 ã€ãè¿ãããå Žåã¯ã©ãã§ããããïŒ
// Copyright 2025 Google LLC // SPDX-License-Identifier: Apache-2.0 fn multiple(a: &i32, b: &i32) -> &i32 { todo!("Return either `a` or `b`") } fn main() { let mut a = 5; let mut b = 10; let r = multiple(&a, &b); // ã©ã¡ãããŸã åçšãããŠããã®ã§ããããïŒ // ã©ã¡ãã®å€æŽãèš±å¯ãããã¹ãã§ããããïŒ a += 7; b += 7; dbg!(r); }
-
ãã®ã³ãŒãã¯çŸåšãã©ã€ãã¿ã€ã 泚éãè¶³ããªãããã³ã³ãã€ã«ã§ããŸãããã³ã³ãã€ã«ã§ããããã«ããåã«ããã®æ©äŒã䜿ã£ãŠãã©ã®åŒæ°ã®åçšãæ»ãå€ã«ãã£ãŠå»¶é·ãããã¹ãããåè¬è ã«èããŠããããŸãããã
-
multipleã«ã¯ 2 ã€ã®åçšãæž¡ãããã®ãã¡ 1 ã€ãæ»ã£ãŠããããšã«ãªããããåŒæ°ã®ã©ã€ãã¿ã€ã ã®ãã¡ 1 ã€ã®åçšãå»¶é·ããå¿ èŠããããŸããã©ã¡ããå»¶é·ãã¹ãã§ããããïŒããã倿ããã«ã¯multipleã®æ¬äœãèŠãå¿ èŠãããã§ããããïŒ -
åçšãã§ãã¯ãè¡ãéãã³ã³ãã€ã©ã¯å€ã«æµãåºãåçšãæšè«ããããã«
multipleã®æ¬äœãèŠãŸããã代ããã«ãåçšè§£æã®ããã«é¢æ°ã·ã°ããã£ã ããèŠãŸãã -
ãã®å Žåãè¿ãããåç §ã«ãã£ãŠ
aãšbã®ã©ã¡ããåçšãããã®ãã倿ããã®ã«ååãªæ å ±ããããŸãããåè¬è ã«ã³ã³ãã€ã©ãšã©ãŒãèŠããŠãã©ã€ãã¿ã€ã æ§æãå°å ¥ããŸãããã// Copyright 2025 Google LLC // SPDX-License-Identifier: Apache-2.0 fn multiple<'a>(a: &'a i32, b: &'a i32) -> &'a i32 { ... }
äž¡æ¹ãåçšãã
ãã®ã±ãŒã¹ã§ã¯ãa ãŸã㯠b ã®ãããããè¿ãããå¯èœæ§ã®ãã颿°ããããŸãããã®å Žåãã©ã€ãã¿ã€ã 泚éã䜿ã£ãŠãäž¡æ¹ã®åçšãæ»ãå€ã«æµã蟌ãå¯èœæ§ãããããšãã³ã³ãã€ã©ã«äŒããŸãã
// Copyright 2025 Google LLC // SPDX-License-Identifier: Apache-2.0 fn pick<'a>(c: bool, a: &'a i32, b: &'a i32) -> &'a i32 { if c { a } else { b } } fn main() { let mut a = 5; let mut b = 10; let r = pick(true, &a, &b); // ã©ã¡ãããŸã åçšãããŠããã§ããããïŒ // ã©ã¡ããã®å€æŽã¯èš±å¯ãããã¹ãã§ããããïŒ // a += 7; // b += 7; dbg!(r); }
-
pick颿°ã¯cã®å€ã«å¿ããŠaãŸãã¯bã®ãããããè¿ããŸããã€ãŸããã©ã¡ããè¿ããããã¯ã³ã³ãã€ã«æã«ã¯ããããŸããã -
ãããã³ã³ãã€ã©ã«è¡šçŸããããã«ã
aãšbã®äž¡æ¹ãããã³æ»ãå€ã®åã«åãã©ã€ãã¿ã€ã ã䜿ããŸããããã¯ãè¿ãããåç §ãaãšbã®äž¡æ¹ãåçšããããšãæå³ããŸãïŒ -
ã³ã¡ã³ãã¢ãŠããããŠãã 2 è¡ãäž¡æ¹ãšãæå¹ã«ããŠãå®è¡æã«ã¯ãã®äžæ¹ã ããæããŠããŠãã
rãaãšbã®äž¡æ¹ãåçšããŠããããšã瀺ããŠãã ããã -
pickã®æåã®åŒæ°ã倿ŽããŠãaãšbã®ã©ã¡ããè¿ããããã«ãããããçµæãåãã§ããããšã瀺ããŠãã ããã
1 ã€ãåçšãã
ãã®äŸã§ã¯ find_nearest ã¯è€æ°ã®åçšãåãåããŸããããã®ãã¡ 1 ã€ã ããè¿ããŸããã©ã€ãã¿ã€ã 泚éã«ãããè¿ãããåçšã察å¿ããåŒæ°ã®åçšã«æç€ºçã«çµã³ä»ããããŠããŸãã
// Copyright 2025 Google LLC // SPDX-License-Identifier: Apache-2.0 #[derive(Debug)] struct Point(i32, i32); /// `points` ãã `query` ã«æãè¿ãç¹ãæ¢ããŸãã /// `points` ã«ã¯å°ãªããšã 1 ã€ã®ç¹ããããšä»®å®ããŸãã fn find_nearest<'a>(points: &'a [Point], query: &Point) -> &'a Point { fn cab_distance(p1: &Point, p2: &Point) -> i32 { (p1.0 - p2.0).abs() + (p1.1 - p2.1).abs() } let mut nearest = None; for p in points { if let Some((_, nearest_dist)) = nearest { let dist = cab_distance(p, query); if dist < nearest_dist { nearest = Some((p, dist)); } } else { nearest = Some((p, cab_distance(p, query))); }; } nearest.map(|(p, _)| p).unwrap() // query // 代ããã«ãããè¡ããšã©ããªããŸããïŒ } fn main() { let points = &[Point(1, 0), Point(1, 0), Point(-1, 0), Point(0, -1)]; let query = Point(0, 2); let nearest = find_nearest(points, &query); // ãã®æç¹ã§ã¯ã`query` ã¯åçšãããŠããŸããã drop(query); dbg!(nearest); }
-
find_nearestã®å®çŸ©ãæããããã§ã颿°ã·ã°ããã£ã«ããæ³šç®ã§ããããã«ãããšåœ¹ç«ã€ãããããŸããã颿°å ã®å®éã®ããžãã¯ã¯ããè€éã§ãåçšè§£æãšããç®çã«ãããŠã¯éèŠã§ã¯ãããŸããã -
find_nearestãåŒã³åºãããšããè¿ãããåç §ã¯queryãåçšããªããããnearestããŸã æå¹ãªéã§ãqueryãç Žæ£ã§ããŸãã -
ã§ã¯ã誀ã£ãåçšãè¿ããšã©ããªãã§ããããïŒ
find_nearestã®æåŸã®è¡ã倿ŽããŠã代ããã«queryãè¿ãããã«ããŠãã ãããã³ã³ãã€ã©ãšã©ãŒãåè¬è ã«èŠããŠãã ããã -
æåã«ããã¹ãããšã¯ã
queryã«ã©ã€ãã¿ã€ã 泚éã远å ããããšã§ããfind_nearestã« 2 ã€ç®ã®ã©ã€ãã¿ã€ã'bã远å ã§ããããšãåè¬è ã«ç€ºããŠãã ããã -
æ°ãããšã©ãŒãåè¬è ã«èŠããŠãã ãããåçšãã§ãã«ãŒã¯ã颿°æ¬äœã®ããžãã¯ãå®éã«æ£ããã©ã€ãã¿ã€ã ãæã€åç §ãè¿ããŠããããšãæ€èšŒãããã®é¢æ°ã颿°ã·ã°ããã£ã§å®ããããå¥çŽã«åŸãããã«åŒ·å¶ããŸãã
ããã«æ¢ã
-
ãšã©ãŒå ã® âhelpâ ã¡ãã»ãŒãžã«ã¯ãã©ã€ãã¿ã€ã å¢ç
'b: 'aã远å ããŠ'bãå°ãªããšã'aãšåãã ãçåããããšã瀺ãããšããããã®å Žåã¯queryãè¿ããããã«ãªããŸããããã¯ã©ã€ãã¿ã€ã ã®ãµãã¿ã€ãã³ã°ã®äŸã§ãããããçãã©ã€ãã¿ã€ã ãæåŸ ãããå Žæã§ãããé·ãã©ã€ãã¿ã€ã ãè¿ããããã«ãããã®ã§ãã -
'staticã©ã€ãã¿ã€ã ãè¿ãããšã§ããããšãã°static倿°ãžã®åç §ãè¿ãããšã§ãåæ§ã®ããšãã§ããŸãã'staticã©ã€ãã¿ã€ã ã¯ä»ã®ã©ã®ã©ã€ãã¿ã€ã ãããé·ãããšãä¿èšŒãããŠãããããããçãã©ã€ãã¿ã€ã ã®ä»£ããã«è¿ããŠãåžžã«å®å šã§ãã
ã©ã€ãã¿ã€ã çç¥
颿°ã®åŒæ°ãšæ»ãå€ã®ã©ã€ãã¿ã€ã ã¯å®å šã«æå®ãããŠããå¿ èŠããããŸãããRust ã§ã¯å€ãã®å Žåã ããã€ãã®åçŽãªã«ãŒã« ã«ãã£ãŠã©ã€ãã¿ã€ã ãçç¥ã§ããŸãã ããã¯æšè«ã§ã¯ãªããåãªãæ§æäžã®çç¥èšæ³ã§ãã
- ã©ã€ãã¿ã€ã 泚éãæããªãååŒæ°ã«ã¯ãã©ã€ãã¿ã€ã ã 1 ã€äžããããŸãã
- åŒæ°ã®ã©ã€ãã¿ã€ã ã 1 ã€ãããªãå Žåããã®ã©ã€ãã¿ã€ã ãæ³šéã®ãªããã¹ãŠã®æ»ãå€ã«äžããããŸãã
- åŒæ°ã®ã©ã€ãã¿ã€ã ãè€æ°ããå Žåã§ããæåã®ãã®ã
selfã«å¯Ÿãããã®ã§ããã°ããã®ã©ã€ãã¿ã€ã ãæ³šéã®ãªããã¹ãŠã®æ»ãå€ã«äžããããŸãã
// èäœæš© 2024 Google LLC // SPDX-License-Identifier: Apache-2.0 fn only_args(a: &i32, b: &i32) { todo!(); } fn identity(a: &i32) -> &i32 { a } struct Foo(i32); impl Foo { fn get(&self, other: &i32) -> &i32 { &self.0 } }
-
ã©ã€ãã¿ã€ã çç¥ã«ãŒã«ãåãµã³ãã«é¢æ°ã«ã©ã®ããã«é©çšããããé ã«ç¢ºèªããŠãã ããã
only_args㯠1 ã€ç®ã®ã«ãŒã«ã§å®æããidentity㯠2 ã€ç®ã§å®æããFoo::get㯠3 ã€ç®ã§å®æããŸãã -
3 ã€ã®çç¥ã«ãŒã«ãé©çšããŠããã¹ãŠã®ã©ã€ãã¿ã€ã ãåãŸããªãå Žåã¯ã泚éãæåã§è¿œå ããããã«æç€ºããã³ã³ãã€ã©ãšã©ãŒã衚瀺ãããŸãã
ããŒã¿æ§é ã«ãããã©ã€ãã¿ã€ã
ããŒã¿åãåçšããŒã¿ãä¿æããå Žåã¯ãã©ã€ãã¿ã€ã 泚éãä»ããå¿ èŠããããŸãã
// Copyright 2024 Google LLC // SPDX-License-Identifier: Apache-2.0 #[derive(Debug)] enum HighlightColor { Pink, Yellow, } #[derive(Debug)] struct Highlight<'document> { slice: &'document str, color: HighlightColor, } fn main() { let doc = String::from("The quick brown fox jumps over the lazy dog."); let noun = Highlight { slice: &doc[16..19], color: HighlightColor::Yellow }; let verb = Highlight { slice: &doc[20..25], color: HighlightColor::Pink }; // drop(doc); dbg!(noun); dbg!(verb); }
- äžã®äŸã§ã¯ã
Highlightã«ã€ããããæ³šéã«ãããå«ãŸããŠãã&strã®å ããŒã¿ã¯ããã®ããŒã¿ã䜿çšããã©ã®Highlightã®ã€ã³ã¹ã¿ã³ã¹ãšåãã ãããããã¯ãã以äžé·ãçåããŠããªããã°ãªããªãããšãä¿èšŒãããŸããæ§é äœã¯ããããåç §ããããŒã¿ããé·ãçåããããšã¯ã§ããŸããã nounãŸãã¯verbã®ã©ã€ãã¿ã€ã ãçµããåã«docãããããããããšãåçšãã§ãã«ãŒã¯ãšã©ãŒãåºããŸãã- åçšããŒã¿ãæã€åã§ã¯ããŠãŒã¶ãŒã¯å ã®ããŒã¿ãä¿æãç¶ããå¿ èŠããããŸããããã¯è»œéãªãã¥ãŒãäœæããã®ã«äŸ¿å©ã§ãããäžè¬ã«ã¯ãã䜿ãã«ãããªããŸãã
- å¯èœã§ããã°ãããŒã¿æ§é ããã®ããŒã¿ãçŽæ¥ææããããã«ããŠãã ããã
- å éšã«è€æ°ã®åç §ãæã€æ§é äœã§ã¯ãè€æ°ã®ã©ã€ãã¿ã€ã 泚éãå¿ èŠã«ãªãããšããããŸããããã¯ãæ§é äœèªäœã®ã©ã€ãã¿ã€ã ã«å ããŠãåç §å士ã®ã©ã€ãã¿ã€ã é¢ä¿ã衚çŸããå¿ èŠãããå Žåã«å¿ èŠã§ããããããã±ãŒã¹ã¯éåžžã«é«åºŠãªãŠãŒã¹ã±ãŒã¹ã§ãã
æŒç¿: Protobuf ã®ããŒã¹
ãã®æŒç¿ã§ã¯ãprotobuf ãã€ããªãšã³ã³ãŒãã£ã³ã°ã® ããŒãµãŒãäœæããŸããå¿é ã¯ãããŸãããèŠãç®ã»ã©è€éã§ã¯ãããŸããïŒããã¯ãããŒã¿ã®ã¹ã©ã€ã¹ãåãæž¡ãäžè¬çãªããŒã¹ ãã¿ãŒã³ã瀺ããŠããŸããåºã«ãªãããŒã¿èªäœãã³ããŒãããããšã¯ãããŸããã
protobuf ã¡ãã»ãŒãžãå®å
šã«ããŒã¹ããã«ã¯ããã£ãŒã«ãçªå·ã§çŽ¢åŒä»ããããåãã£ãŒã«ãã®åã ç¥ã£ãŠããå¿
èŠããããŸããããã¯éåžž proto ãã¡ã€ã«ã§æäŸãããŸãããã® æŒç¿ã§ã¯ããã®æ
å ±ããåãã£ãŒã«ãããšã«åŒã³åºããã颿°å
ã® match æã« åã蟌ã¿ãŸãã
次㮠proto ã䜿ããŸãã
message PhoneNumber {
optional string number = 1;
optional string type = 2;
}
message Person {
optional string name = 1;
optional int32 id = 2;
repeated PhoneNumber phones = 3;
}
ã¡ãã»ãŒãž
proto ã¡ãã»ãŒãžã¯ããã£ãŒã«ãã 1 ã€ãã€é çªã«äžŠãã ãã®ãšããŠãšã³ã³ãŒããããŸããåãã£ãŒã«ã㯠ãtagããšããã«ç¶ãå€ã§å®è£
ãããŸããtag ã«ã¯ãã£ãŒã«ãçªå· ïŒããšãã°ãPerson ã¡ãã»ãŒãžã® id ãã£ãŒã«ããªã 2ïŒãšããã€ãã¹ããªãŒã ãã ãã€ããŒããã©ã®ããã«æ±ºå®ãã¹ãããå®çŸ©ããã¯ã€ã€ãŒåãå«ãŸããŸããããã㯠1 ã€ã®æŽæ°ã«ãŸãšãããã以äžã® unpack_tag ã§ãã³ãŒããããŸãã
Varint
tag ãå«ãæŽæ°ã¯ãVARINT ãšåŒã°ããå¯å€é·ãšã³ã³ãŒãã£ã³ã°ã§è¡šçŸãããŸãã 幞ããparse_varint ã¯ä»¥äžã§å®çŸ©æžã¿ã§ãã
ã¯ã€ã€ãŒå
Proto ã§ã¯ããã€ãã®ã¯ã€ã€ãŒåãå®çŸ©ãããŠããŸããããã®æŒç¿ã§äœ¿ãã®ã¯ãã®ãã¡ 2 ã€ã ãã§ãã
Varint ã¯ã€ã€ãŒåã«ã¯ 1 ã€ã® varint ãå«ãŸããPerson.id ã®ãã㪠int32 åã® proto å€ããšã³ã³ãŒãããããã«äœ¿ãããŸãã
Len ã¯ã€ã€ãŒåã«ã¯ãvarint ã§è¡šçŸãããé·ããšãããã«ç¶ããã®ãã€ãæ°ã® ãã€ããŒããå«ãŸããŸããããã¯ãPerson.name ã®ãã㪠string åã® proto å€ã ãšã³ã³ãŒãããããã«äœ¿ãããŸãããŸããPerson.phones ã®ããã«ãµãã¡ãã»ãŒãžã å«ã proto å€ã®ãšã³ã³ãŒãã«ã䜿ããããã®å Žåãã€ããŒãã«ã¯ãµãã¡ãã»ãŒãžã® ãšã³ã³ãŒãã£ã³ã°ãå«ãŸããŸãã
æŒç¿
äžããããã³ãŒãã§ã¯ãPerson ãš PhoneNumber ã®ãã£ãŒã«ããåŠçããã³ãŒã«ããã¯ãšã ã¡ãã»ãŒãžãããŒã¹ããŠãããã®ã³ãŒã«ããã¯åŒã³åºãåã«å€æããåŠçãå®çŸ©ãããŠããŸãã
ããªãã«æ®ãããŠããã®ã¯ãparse_field 颿°ãšãPerson ããã³ PhoneNumber ã«å¯Ÿãã ProtoMessage ãã¬ã€ããå®è£
ããããšã§ãã
// Copyright 2024 Google LLC // SPDX-License-Identifier: Apache-2.0 /// A wire type as seen on the wire. enum WireType { /// The Varint WireType indicates the value is a single VARINT. Varint, // The I64 WireType indicates that the value is precisely 8 bytes in // little-endian order containing a 64-bit signed integer or double type. //I64, -- not needed for this exercise /// The Len WireType indicates that the value is a length represented as a /// VARINT followed by exactly that number of bytes. Len, // The I32 WireType indicates that the value is precisely 4 bytes in // little-endian order containing a 32-bit signed integer or float type. //I32, -- not needed for this exercise } #[derive(Debug)] /// A field's value, typed based on the wire type. enum FieldValue<'a> { Varint(u64), //I64(i64), -- not needed for this exercise Len(&'a [u8]), //I32(i32), -- not needed for this exercise } #[derive(Debug)] /// A field, containing the field number and its value. struct Field<'a> { field_num: u64, value: FieldValue<'a>, } trait ProtoMessage<'a>: Default { fn add_field(&mut self, field: Field<'a>); } impl From<u64> for WireType { fn from(value: u64) -> Self { match value { 0 => WireType::Varint, //1 => WireType::I64, -- not needed for this exercise 2 => WireType::Len, //5 => WireType::I32, -- not needed for this exercise _ => panic!("Invalid wire type: {value}"), } } } impl<'a> FieldValue<'a> { fn as_str(&self) -> &'a str { let FieldValue::Len(data) = self else { panic!("Expected string to be a `Len` field"); }; std::str::from_utf8(data).expect("Invalid string") } fn as_bytes(&self) -> &'a [u8] { let FieldValue::Len(data) = self else { panic!("Expected bytes to be a `Len` field"); }; data } fn as_u64(&self) -> u64 { let FieldValue::Varint(value) = self else { panic!("Expected `u64` to be a `Varint` field"); }; *value } } /// Parse a VARINT, returning the parsed value and the remaining bytes. fn parse_varint(data: &[u8]) -> (u64, &[u8]) { for i in 0..7 { let Some(b) = data.get(i) else { panic!("Not enough bytes for varint"); }; if b & 0x80 == 0 { // This is the last byte of the VARINT, so convert it to // a u64 and return it. let mut value = 0u64; for b in data[..=i].iter().rev() { value = (value << 7) | (b & 0x7f) as u64; } return (value, &data[i + 1..]); } } // More than 7 bytes is invalid. panic!("Too many bytes for varint"); } /// Convert a tag into a field number and a WireType. fn unpack_tag(tag: u64) -> (u64, WireType) { let field_num = tag >> 3; let wire_type = WireType::from(tag & 0x7); (field_num, wire_type) } /// Parse a field, returning the remaining bytes fn parse_field(data: &[u8]) -> (Field<'_>, &[u8]) { let (tag, remainder) = parse_varint(data); let (field_num, wire_type) = unpack_tag(tag); let (fieldvalue, remainder) = match wire_type { _ => todo!("ã¯ã€ã€ãŒã¿ã€ãã«å¿ããŠããã£ãŒã«ããæ§ç¯ããå¿ èŠãªéã®ãã€ããæ¶è²»ããŸãã") }; todo!("ãã£ãŒã«ããšãæªæ¶è²»ã®ãã€ããè¿ããŸãã") } /// Parse a message in the given data, calling `T::add_field` for each field in /// the message. /// /// The entire input is consumed. fn parse_message<'a, T: ProtoMessage<'a>>(mut data: &'a [u8]) -> T { let mut result = T::default(); while !data.is_empty() { let parsed = parse_field(data); result.add_field(parsed.0); data = parsed.1; } result } #[derive(Debug, Default)] struct PhoneNumber<'a> { number: &'a str, type_: &'a str, } #[derive(Debug, Default)] struct Person<'a> { name: &'a str, id: u64, phone: Vec<PhoneNumber<'a>>, } // TODO: Person ãš PhoneNumber ã«å¯Ÿã㊠ProtoMessage ãå®è£ ããã #[test] fn test_id() { let person_id: Person = parse_message(&[0x10, 0x2a]); assert_eq!(person_id, Person { name: "", id: 42, phone: vec![] }); } #[test] fn test_name() { let person_name: Person = parse_message(&[ 0x0a, 0x0e, 0x62, 0x65, 0x61, 0x75, 0x74, 0x69, 0x66, 0x75, 0x6c, 0x20, 0x6e, 0x61, 0x6d, 0x65, ]); assert_eq!(person_name, Person { name: "beautiful name", id: 0, phone: vec![] }); } #[test] fn test_just_person() { let person_name_id: Person = parse_message(&[0x0a, 0x04, 0x45, 0x76, 0x61, 0x6e, 0x10, 0x16]); assert_eq!(person_name_id, Person { name: "Evan", id: 22, phone: vec![] }); } #[test] fn test_phone() { let phone: Person = parse_message(&[ 0x0a, 0x00, 0x10, 0x00, 0x1a, 0x16, 0x0a, 0x0e, 0x2b, 0x31, 0x32, 0x33, 0x34, 0x2d, 0x37, 0x37, 0x37, 0x2d, 0x39, 0x30, 0x39, 0x30, 0x12, 0x04, 0x68, 0x6f, 0x6d, 0x65, ]); assert_eq!( phone, Person { name: "", id: 0, phone: vec![PhoneNumber { number: "+1234-777-9090", type_: "home" },], } ); } // Put that all together into a single parse. #[test] fn test_full_person() { let person: Person = parse_message(&[ 0x0a, 0x07, 0x6d, 0x61, 0x78, 0x77, 0x65, 0x6c, 0x6c, 0x10, 0x2a, 0x1a, 0x16, 0x0a, 0x0e, 0x2b, 0x31, 0x32, 0x30, 0x32, 0x2d, 0x35, 0x35, 0x35, 0x2d, 0x31, 0x32, 0x31, 0x32, 0x12, 0x04, 0x68, 0x6f, 0x6d, 0x65, 0x1a, 0x18, 0x0a, 0x0e, 0x2b, 0x31, 0x38, 0x30, 0x30, 0x2d, 0x38, 0x36, 0x37, 0x2d, 0x35, 0x33, 0x30, 0x38, 0x12, 0x06, 0x6d, 0x6f, 0x62, 0x69, 0x6c, 0x65, ]); assert_eq!( person, Person { name: "maxwell", id: 42, phone: vec![ PhoneNumber { number: "+1202-555-1212", type_: "home" }, PhoneNumber { number: "+1800-867-5308", type_: "mobile" }, ] } ); }
- ãã®æŒç¿ã§ã¯ãprotobuf ã®ããŒã¹ã倱æããå¯èœæ§ã®ããã±ãŒã¹ãããŸããŸã«ãããŸãã ããšãã°ãããŒã¿ãããã¡ã«æ®ã£ãŠãããã€ãæ°ã 4 æªæºãªã®ã«
i32ãããŒã¹ããããšãã å Žåã§ããéåžžã® Rust ã³ãŒãã§ããã°ãããResultåæåã§åŠçããŸããã ãã®æŒç¿ã§ã¯ç°¡åã«ããããããšã©ãŒãçºçããå Žå㯠panic ããŸãã4 æ¥ç®ã«ã¯ã Rust ã®ãšã©ãŒãã³ããªã³ã°ãããã«è©³ããæ±ããŸãã
è§£ç
// Copyright 2024 Google LLC // SPDX-License-Identifier: Apache-2.0 /// A wire type as seen on the wire. enum WireType { /// The Varint WireType indicates the value is a single VARINT. Varint, // The I64 WireType indicates that the value is precisely 8 bytes in // little-endian order containing a 64-bit signed integer or double type. //I64, -- not needed for this exercise /// The Len WireType indicates that the value is a length represented as a /// VARINT followed by exactly that number of bytes. Len, // The I32 WireType indicates that the value is precisely 4 bytes in // little-endian order containing a 32-bit signed integer or float type. //I32, -- not needed for this exercise } #[derive(Debug)] /// A field's value, typed based on the wire type. enum FieldValue<'a> { Varint(u64), //I64(i64), -- not needed for this exercise Len(&'a [u8]), //I32(i32), -- not needed for this exercise } #[derive(Debug)] /// A field, containing the field number and its value. struct Field<'a> { field_num: u64, value: FieldValue<'a>, } trait ProtoMessage<'a>: Default { fn add_field(&mut self, field: Field<'a>); } impl From<u64> for WireType { fn from(value: u64) -> Self { match value { 0 => WireType::Varint, //1 => WireType::I64, -- not needed for this exercise 2 => WireType::Len, //5 => WireType::I32, -- not needed for this exercise _ => panic!("Invalid wire type: {value}"), } } } impl<'a> FieldValue<'a> { fn as_str(&self) -> &'a str { let FieldValue::Len(data) = self else { panic!("Expected string to be a `Len` field"); }; std::str::from_utf8(data).expect("Invalid string") } fn as_bytes(&self) -> &'a [u8] { let FieldValue::Len(data) = self else { panic!("Expected bytes to be a `Len` field"); }; data } fn as_u64(&self) -> u64 { let FieldValue::Varint(value) = self else { panic!("Expected `u64` to be a `Varint` field"); }; *value } } /// Parse a VARINT, returning the parsed value and the remaining bytes. fn parse_varint(data: &[u8]) -> (u64, &[u8]) { for i in 0..7 { let Some(b) = data.get(i) else { panic!("Not enough bytes for varint"); }; if b & 0x80 == 0 { // This is the last byte of the VARINT, so convert it to // a u64 and return it. let mut value = 0u64; for b in data[..=i].iter().rev() { value = (value << 7) | (b & 0x7f) as u64; } return (value, &data[i + 1..]); } } // More than 7 bytes is invalid. panic!("Too many bytes for varint"); } /// Convert a tag into a field number and a WireType. fn unpack_tag(tag: u64) -> (u64, WireType) { let field_num = tag >> 3; let wire_type = WireType::from(tag & 0x7); (field_num, wire_type) } /// Parse a field, returning the remaining bytes fn parse_field(data: &[u8]) -> (Field<'_>, &[u8]) { let (tag, remainder) = parse_varint(data); let (field_num, wire_type) = unpack_tag(tag); let (fieldvalue, remainder) = match wire_type { WireType::Varint => { let (value, remainder) = parse_varint(remainder); (FieldValue::Varint(value), remainder) } WireType::Len => { let (len, remainder) = parse_varint(remainder); let len = len as usize; // cast for simplicity let (value, remainder) = remainder.split_at(len); (FieldValue::Len(value), remainder) } }; (Field { field_num, value: fieldvalue }, remainder) } /// Parse a message in the given data, calling `T::add_field` for each field in /// the message. /// /// The entire input is consumed. fn parse_message<'a, T: ProtoMessage<'a>>(mut data: &'a [u8]) -> T { let mut result = T::default(); while !data.is_empty() { let parsed = parse_field(data); result.add_field(parsed.0); data = parsed.1; } result } #[derive(PartialEq)] #[derive(Debug, Default)] struct PhoneNumber<'a> { number: &'a str, type_: &'a str, } #[derive(PartialEq)] #[derive(Debug, Default)] struct Person<'a> { name: &'a str, id: u64, phone: Vec<PhoneNumber<'a>>, } impl<'a> ProtoMessage<'a> for Person<'a> { fn add_field(&mut self, field: Field<'a>) { match field.field_num { 1 => self.name = field.value.as_str(), 2 => self.id = field.value.as_u64(), 3 => self.phone.push(parse_message(field.value.as_bytes())), _ => {} // skip everything else } } } impl<'a> ProtoMessage<'a> for PhoneNumber<'a> { fn add_field(&mut self, field: Field<'a>) { match field.field_num { 1 => self.number = field.value.as_str(), 2 => self.type_ = field.value.as_str(), _ => {} // skip everything else } } } #[test] fn test_id() { let person_id: Person = parse_message(&[0x10, 0x2a]); assert_eq!(person_id, Person { name: "", id: 42, phone: vec![] }); } #[test] fn test_name() { let person_name: Person = parse_message(&[ 0x0a, 0x0e, 0x62, 0x65, 0x61, 0x75, 0x74, 0x69, 0x66, 0x75, 0x6c, 0x20, 0x6e, 0x61, 0x6d, 0x65, ]); assert_eq!(person_name, Person { name: "beautiful name", id: 0, phone: vec![] }); } #[test] fn test_just_person() { let person_name_id: Person = parse_message(&[0x0a, 0x04, 0x45, 0x76, 0x61, 0x6e, 0x10, 0x16]); assert_eq!(person_name_id, Person { name: "Evan", id: 22, phone: vec![] }); } #[test] fn test_phone() { let phone: Person = parse_message(&[ 0x0a, 0x00, 0x10, 0x00, 0x1a, 0x16, 0x0a, 0x0e, 0x2b, 0x31, 0x32, 0x33, 0x34, 0x2d, 0x37, 0x37, 0x37, 0x2d, 0x39, 0x30, 0x39, 0x30, 0x12, 0x04, 0x68, 0x6f, 0x6d, 0x65, ]); assert_eq!( phone, Person { name: "", id: 0, phone: vec![PhoneNumber { number: "+1234-777-9090", type_: "home" },], } ); } // Put that all together into a single parse. #[test] fn test_full_person() { let person: Person = parse_message(&[ 0x0a, 0x07, 0x6d, 0x61, 0x78, 0x77, 0x65, 0x6c, 0x6c, 0x10, 0x2a, 0x1a, 0x16, 0x0a, 0x0e, 0x2b, 0x31, 0x32, 0x30, 0x32, 0x2d, 0x35, 0x35, 0x35, 0x2d, 0x31, 0x32, 0x31, 0x32, 0x12, 0x04, 0x68, 0x6f, 0x6d, 0x65, 0x1a, 0x18, 0x0a, 0x0e, 0x2b, 0x31, 0x38, 0x30, 0x30, 0x2d, 0x38, 0x36, 0x37, 0x2d, 0x35, 0x33, 0x30, 0x38, 0x12, 0x06, 0x6d, 0x6f, 0x62, 0x69, 0x6c, 0x65, ]); assert_eq!( person, Person { name: "maxwell", id: 42, phone: vec![ PhoneNumber { number: "+1202-555-1212", type_: "home" }, PhoneNumber { number: "+1800-867-5308", type_: "mobile" }, ] } ); }
Day 4 ãžãããã
ãããŸã§ã§ãã³ã¢èšèªãšãã®ç¬èªã®å®å šæ§ã¢ãã«ãç¿åŸããŸãã:
- åºç€ãšæœè±¡å: ãã¬ã€ãããžã§ããªã¯ã¹ãæšæºã©ã€ãã©ãªã
- æææš©: ã ãŒãã»ãã³ãã£ã¯ã¹ãš
Dropãã¬ã€ãã - ã¡ã¢ãªç®¡ç: åçšèŠåïŒ
&ãš&mutïŒããã³ã©ã€ãã¿ã€ã ã - ã¹ããŒããã€ã³ã¿: è€éãªããŒã¿æ§é ã®ããã®
BoxãRcãRefCellã
ããã§ãRust ãã³ã³ãã€ã«æã«ã©ã®ããã«ã¡ã¢ãªå®å šæ§ãä¿èšŒããã®ããçè§£ã§ããŸããïŒä»æ¥ã¯ããã®ç¥èã é©çšããŠå ç¢ã§å€§èŠæš¡ãªã¢ããªã±ãŒã·ã§ã³ãæ§ç¯ããããšã«çŠç¹ãåœãŠãŸãã
ã¹ã±ãžã¥ãŒã«
session outline
ã€ãã¬ãŒã¿
segment outline
ã€ãã¬ãŒã¿ãå¿ èŠãªçç±
é åã®å 容ãå埩åŠçãããå Žåã¯ã次ãå®çŸ©ããå¿ èŠããããŸãã
- å埩åŠçã®ã©ããŸã§é²ãã§ãããã远跡ããããã®ç¶æ ãããšãã° ã€ã³ããã¯ã¹ã
- å埩åŠçããã€çµäºããããå€å®ããæ¡ä»¶ã
- ã«ãŒãããšã«ååŸ©ç¶æ ãæŽæ°ããããžãã¯ã
- ãã®ååŸ©ç¶æ ã䜿ã£ãŠåèŠçŽ ãååŸããããžãã¯ã
C ã¹ã¿ã€ã«ã® for ã«ãŒãã§ã¯ãããããçŽæ¥å®£èšããŸãã
for (int i = 0; i < array_len; i += 1) {
int elem = array[i];
}
Rust ã§ã¯ããã®ç¶æ ãšããžãã¯ããŸãšããŠãã€ãã¬ãŒã¿ããšåŒã°ãã ãªããžã§ã¯ãã«ããŸãã
-
ãã®ã¹ã©ã€ãã§ã¯ãRust ã®ã€ãã¬ãŒã¿ãå éšã§äœãããŠãããã説æããããã®æèã瀺ããŸããããã§ã¯ã ïŒããããïŒãªãã¿ã®ãã C ã¹ã¿ã€ã«ã®
forã«ãŒããšããæ§æã䜿ã£ãŠã å埩åŠçã«ã¯äœããã®ç¶æ ãšäœããã®ããžãã¯ãå¿ èŠã§ããããšã瀺ãããã®ããã§æ¬¡ã®ã¹ã©ã€ãã§ ã€ãã¬ãŒã¿ãããããã©ã®ããã«ãŸãšãããã瀺ããŸãã -
Rust ã«ã¯ C ã¹ã¿ã€ã«ã®
forã«ãŒãã¯ãããŸããããåãããšãwhileã§è¡šçŸã§ããŸã:// Copyright 2024 Google LLC // SPDX-License-Identifier: Apache-2.0 let array = [2, 4, 6, 8]; let mut i = 0; while i < array.len() { let elem = array[i]; i += 1; }
ããã«è©³ãã
C ãš C++ ã§ã¯ãfor ã䜿ã£ãŠé
åã®å埩åŠçã衚ãå¥ã®æ¹æ³ããããŸããé
åã® å
é ãžã®ãã€ã³ã¿ãšæ«å°Ÿãžã®ãã€ã³ã¿ã䜿ãããããã®ãã€ã³ã¿ã æ¯èŒããŠãã«ãŒãããã€çµäºãã¹ãããå€å®ã§ããŸãã
for (int *ptr = array; ptr < array + len; ptr += 1) {
int elem = *ptr;
}
åè¬è ãã質åãããã°ãããã Rust ã®ã¹ã©ã€ã¹ããã³é åã® ã€ãã¬ãŒã¿ãå éšã§åäœããä»çµã¿ã§ãããšèª¬æã§ããŸãïŒãã ããRust ã®ã€ãã¬ãŒã¿ãšããŠå®è£ ãããŠããŸãïŒã
Iterator ãã¬ã€ã
Iterator ãã¬ã€ãã¯ããªããžã§ã¯ããå€ã®ã·ãŒã±ã³ã¹ãçæããããã«ã©ã®ããã«äœ¿çšã§ããããå®çŸ©ããŸããããšãã°ãã¹ã©ã€ã¹ã®èŠçŽ ãçæã§ããã€ãã¬ãŒã¿ãäœæãããå Žåãæ¬¡ã®ããã«ãªããŸãã
// Copyright 2023 Google LLC // SPDX-License-Identifier: Apache-2.0 struct SliceIter<'s> { slice: &'s [i32], i: usize, } impl<'s> Iterator for SliceIter<'s> { type Item = &'s i32; fn next(&mut self) -> Option<Self::Item> { if self.i == self.slice.len() { None } else { let next = &self.slice[self.i]; self.i += 1; Some(next) } } } fn main() { let slice = &[2, 4, 6, 8]; let iter = SliceIter { slice, i: 0 }; for elem in iter { dbg!(elem); } }
-
SliceIterã®äŸã¯ãåã®ã¹ã©ã€ãã§ç€ºãã C ã¹ã¿ã€ã«ã®forã«ãŒããšåãããžãã¯ãå®è£ ããŠããŸãã -
åè¬è ã«ãã€ãã¬ãŒã¿ã¯é å»¶è©äŸ¡ãããããšãææããŠãã ãããã€ãã¬ãŒã¿ãäœæããŠãæ§é äœãåæåãããã ãã§ããã以å€ã®åŠçã¯è¡ãããŸããã
nextã¡ãœãããåŒã³åºããããŸã§ãäœã®åŠçãçºçããŸããã -
ã€ãã¬ãŒã¿ã¯æéã§ããå¿ èŠã¯ãããŸãããæ°žé ã«å€ãçæãç¶ããã€ãã¬ãŒã¿ãå®å šã«æå¹ã§ããããšãã°ã
0..ã®ãããªåéåºéã¯ãæŽæ°ãªãŒããŒãããŒãçºçãããŸã§é²ã¿ç¶ããŸãã
ããã«èª¿ã¹ã
-
SliceIterã®ãå®éã®ãçã¯ãæšæºã©ã€ãã©ãªå ã®slice::Iteråã§ãããã ããå®éã®çã§ã¯å¢çãã§ãã¯ããªããããã«ãå éšã§ã¯ã€ã³ããã¯ã¹ã®ä»£ããã«ãã€ã³ã¿ã䜿çšããŠããŸãã -
SliceIterã®äŸã¯ãåç §ãå«ãæ§é äœã®è¯ãäŸã§ããããã®ããã©ã€ãã¿ã€ã 泚éã䜿çšããŠããŸãã -
SliceIterã«ãžã§ããªãã¯ãã©ã¡ãŒã¿ã远å ããŠãä»»æã®çš®é¡ã®ã¹ã©ã€ã¹ïŒ&[i32]ã ãã§ãªãïŒã§åäœã§ããããã«ããããšã瀺ããŸãã
Iterator ã®ãã«ããŒã¡ãœãã
ã€ãã¬ãŒã¿ãã©ã®ããã«æ¯ãèãããå®çŸ©ãã next ã¡ãœããã«å ããŠã Iterator ãã¬ã€ãã¯ãã«ã¹ã¿ãã€ãºãããã€ãã¬ãŒã¿ãæ§ç¯ããããã«äœ¿ãã 70 å以äžã®ãã«ããŒã¡ãœãããæäŸããŸãã
// Copyright 2024 Google LLC // SPDX-License-Identifier: Apache-2.0 fn main() { let result: i32 = (1..=10) // 1 ãã 10 ãŸã§ã®ç¯å²ãäœæãã .filter(|x| x % 2 == 0) // å¶æ°ã®ã¿ãä¿æãã .map(|x| x * x) // åæ°ãäºä¹ãã .sum(); // äºä¹ãããã¹ãŠã®æ°ãåèšãã println!("The sum of squares of even numbers from 1 to 10 is: {}", result); }
-
Iteratorãã¬ã€ãã¯ãã³ã¬ã¯ã·ã§ã³ã«å¯Ÿããå€ãã®äžè¬çãªé¢æ°å ããã°ã©ãã³ã°æäœïŒããšãã°mapãfilterãreduceãªã©ïŒãå®è£ ããŠããŸãã ãããã«é¢ãããã¹ãŠã®ããã¥ã¡ã³ãã¯ããã®ãã¬ã€ãã«ãããŸãã -
ãããã®ãã«ããŒã¡ãœããã®å€ãã¯ãå ã®ã€ãã¬ãŒã¿ãåãåããç°ãªãæ¯ãèãã ããæ°ããã€ãã¬ãŒã¿ãçæããŸãããããã¯ãiterator adapter methodsããšããŠç¥ãããŠããŸãã
-
sumãcountã®ãããªäžéšã®ã¡ãœããã¯ãã€ãã¬ãŒã¿ãæ¶è²»ãããã®äžãã ãã¹ãŠã®èŠçŽ ãåãåºããŸãã -
ãããã®ã¡ãœããã¯é£çµããŠäœ¿ããããã«èšèšãããŠãããããå¿ èŠãªããšãæ£ç¢ºã«è¡ã ã«ã¹ã¿ã ã€ãã¬ãŒã¿ãç°¡åã«æ§ç¯ã§ããŸãã
ããã«åŠã¶
- Rust ã®ã€ãã¬ãŒã¿ã¯éåžžã«å¹ççã§ãé«åºŠã«æé©åå¯èœã§ããå€ãã®ã¢ããã¿ ã¡ãœãããçµã¿åãããŠäœãããè€éãªã€ãã¬ãŒã¿ã§ãã£ãŠããåçã®åœä»€åå®è£ ãš åããããå¹ççãªã³ãŒãã«ãªããŸãã
collect
collect ã¡ãœããã䜿ããšãIterator ããã³ã¬ã¯ã·ã§ã³ãæ§ç¯ã§ããŸãã
// Copyright 2024 Google LLC // SPDX-License-Identifier: Apache-2.0 fn main() { let primes = vec![2, 3, 5, 7]; let prime_squares = primes.into_iter().map(|p| p * p).collect::<Vec<_>>(); println!("prime_squares: {prime_squares:?}"); }
- ã©ã®ã€ãã¬ãŒã¿ã§ã
VecãVecDequeããŸãã¯HashSetã« collect ã§ããŸãã ããŒãšå€ã®ãã¢ïŒã€ãŸã 2 èŠçŽ ã®ã¿ãã«ïŒãçæããã€ãã¬ãŒã¿ã¯ãHashMapãBTreeMapã« collect ããããšãã§ããŸãã
æšæºã©ã€ãã©ãªã®ããã¥ã¡ã³ãã§ãcollect ã®å®çŸ©ãåè¬è
ã«èŠããŠãã ããã ãã®ã¡ãœããã®ãžã§ããªãã¯å B ãæå®ããæ¹æ³ã¯ 2 ã€ãããŸãã
- ãã¿ãŒããã£ãã·ã¥ããäœ¿ãæ¹æ³:
some_iterator.collect::<COLLECTION_TYPE>()ãäžã®äŸã¯ãã®æžãæ¹ã§ãã ããã§äœ¿ãããŠãã_ãšããçç¥èšæ³ã«ãããRust ã¯Vecã®èŠçŽ åãæšè«ã§ããŸãã - åæšè«ãäœ¿ãæ¹æ³:
let prime_squares: Vec<_> = some_iterator.collect(). ãã®åœ¢åŒã䜿ãããã«äŸãæžãæããŠãã ããã
ããã«æ¢ã£ãŠã¿ã
- åè¬è
ããããã©ã®ããã«åãã®ãæ°ã«ãªã£ãããåçš®ã³ã¬ã¯ã·ã§ã³åã ã€ãã¬ãŒã¿ããã©ã®ããã«æ§ç¯ãããããå®çŸ©ããŠãã
FromIteratorãã¬ã€ããåãäžãããšããã§ãããã VecãHashMapãªã©ã«å¯ŸããFromIteratorã®åºæ¬çãªå®è£ ã«å ããŠã ããã«ç¹åããå®è£ ããããIterator<Item = Result<V, E>>ãResult<Vec<V>, E>ã«å€æãããšãã£ã䟿å©ãªããšãã§ããŸããcollectã§å泚éããã°ãã°å¿ èŠã«ãªãçç±ã¯ãæ»ãå€ã®åã«å¯Ÿã㊠ãžã§ããªãã¯ã«ãªã£ãŠããããã§ãããã®ãããå€ãã®å Žåã«ã³ã³ãã€ã©ã æ£ããåãæšè«ãã«ãããªããŸãã
IntoIterator
Iterator ãã¬ã€ãã¯ãã€ãã¬ãŒã¿ãäœæããããšã§ã©ã®ããã« ã€ãã¬ãŒãããã ã瀺ããŸããé¢é£ãããã¬ã€ã IntoIterator ã¯ãããåã«å¯Ÿããã€ãã¬ãŒã¿ã®äœææ¹æ³ãå®çŸ©ããŸãããã㯠for ã«ãŒãã§èªåçã«äœ¿ãããŸãã
// èäœæš© 2023 Google LLC // SPDX-License-Identifier: Apache-2.0 struct Grid { x_coords: Vec<u32>, y_coords: Vec<u32>, } impl IntoIterator for Grid { type Item = (u32, u32); type IntoIter = GridIter; fn into_iter(self) -> GridIter { GridIter { grid: self, i: 0, j: 0 } } } struct GridIter { grid: Grid, i: usize, j: usize, } impl Iterator for GridIter { type Item = (u32, u32); fn next(&mut self) -> Option<(u32, u32)> { if self.i >= self.grid.x_coords.len() { self.i = 0; self.j += 1; if self.j >= self.grid.y_coords.len() { return None; } } let res = Some((self.grid.x_coords[self.i], self.grid.y_coords[self.j])); self.i += 1; res } } fn main() { let grid = Grid { x_coords: vec![3, 5, 7, 9], y_coords: vec![10, 20, 30, 40] }; for (x, y) in grid { println!("point = {x}, {y}"); } }
IntoIteratorã¯ãfor ã«ãŒããåäœããããã¬ã€ãã§ããããã¯Vec<T>ã®ãããªã³ã¬ã¯ã·ã§ã³åããããããžã®åç §ã§ãã&Vec<T>ã&[T]ã«ãã£ãŠå®è£ ãããŠããŸããç¯å²ããããå®è£ ããŠããŸããããããfor i in some_vec { .. }ã§ãã¯ã¿ãã€ãã¬ãŒãã§ããäžæ¹ã§ãsome_vec.next()ã¯ååšããªãçç±ã§ãã
IntoIterator ã®ããã¥ã¡ã³ããåç
§ããŠãã ãããIntoIterator ã®ãã¹ãŠã®å®è£
ã¯ã2 ã€ã®åã宣èšããªããã°ãªããŸããã
Item:i8ã®ãããªãã€ãã¬ãŒã察象ã®åIntoIter:into_iterã¡ãœãããè¿ãIteratorå
IntoIter ãš Item ã¯çµã³ä»ããŠããããšã«æ³šæããŠãã ãããã€ãã¬ãŒã¿ã¯åã Item åãæããªããã°ãªããããã㯠Option<Item> ãè¿ãããšãæå³ããŸã
ãã®äŸã§ã¯ãx 座æšãš y 座æšã®ãã¹ãŠã®çµã¿åãããã€ãã¬ãŒãããŠããŸãã
main ã§ã°ãªããã 2 åã€ãã¬ãŒãããŠã¿ãŠãã ããããªãããã¯å€±æããã®ã§ãããããIntoIterator::into_iter 㯠self ã®æææš©ãåãåãããšã«æ³šæããŠãã ããã
ãã®åé¡ã¯ã&Grid ã«å¯Ÿã㊠IntoIterator ãå®è£
ããåç
§ã§ã€ãã¬ãŒããã GridRefIter ãäœæããããšã§ä¿®æ£ã§ããŸããGridIter ãš GridRefIter ã®äž¡æ¹ãå«ãããŒãžã§ã³ã¯ããã® playground ã§å©çšã§ããŸãã
åãåé¡ã¯æšæºã©ã€ãã©ãªã®åã§ãçºçããããšããããŸããfor e in some_vector 㯠some_vector ã®æææš©ãååŸãããã®ãã¯ã¿ã®ææãããèŠçŽ ãã€ãã¬ãŒãããŸãã代ããã« for e in &some_vector ã䜿ããšãsome_vector ã®èŠçŽ ãžã®åç
§ãã€ãã¬ãŒãã§ããŸãã
æŒç¿: Iterator ã¡ãœããã®ãã§ãŒã³
ãã®æŒç¿ã§ã¯ãè€éãªèšç®ãå®è£
ããããã«ãIterator ãã¬ã€ãã§æäŸãããŠãã ã¡ãœããã®ããã€ããèŠã€ããŠäœ¿ãå¿
èŠããããŸãã
次ã®ã³ãŒãã https://play.rust-lang.org/ ã«ã³ããŒããŠããã¹ããéãããã«ã㊠ãã ãããã€ãã¬ãŒã¿åŒã䜿çšãããã®çµæã collect ããŠæ»ãå€ãæ§ç¯ããŠãã ããã
// èäœæš© 2023 Google LLC // SPDX-License-Identifier: Apache-2.0 /// Calculate the differences between elements of `values` offset by `offset`, /// wrapping around from the end of `values` to the beginning. /// /// Element `n` of the result is `values[(n+offset)%len] - values[n]`. fn offset_differences(offset: usize, values: Vec<i32>) -> Vec<i32> { todo!() } #[test] fn test_offset_one() { assert_eq!(offset_differences(1, vec![1, 3, 5, 7]), vec![2, 2, 2, -6]); assert_eq!(offset_differences(1, vec![1, 3, 5]), vec![2, 2, -4]); assert_eq!(offset_differences(1, vec![1, 3]), vec![2, -2]); } #[test] fn test_larger_offsets() { assert_eq!(offset_differences(2, vec![1, 3, 5, 7]), vec![4, 4, -4, -4]); assert_eq!(offset_differences(3, vec![1, 3, 5, 7]), vec![6, -2, -2, -2]); assert_eq!(offset_differences(4, vec![1, 3, 5, 7]), vec![0, 0, 0, 0]); assert_eq!(offset_differences(5, vec![1, 3, 5, 7]), vec![2, 2, 2, -6]); } #[test] fn test_degenerate_cases() { assert_eq!(offset_differences(1, vec![0]), vec![0]); assert_eq!(offset_differences(1, vec![1]), vec![0]); let empty: Vec<i32> = vec![]; assert_eq!(offset_differences(1, empty), vec![]); }
è§£ç
// èäœæš© 2023 Google LLC // SPDX-License-Identifier: Apache-2.0 /// Calculate the differences between elements of `values` offset by `offset`, /// wrapping around from the end of `values` to the beginning. /// /// Element `n` of the result is `values[(n+offset)%len] - values[n]`. fn offset_differences(offset: usize, values: Vec<i32>) -> Vec<i32> { let a = values.iter(); let b = values.iter().cycle().skip(offset); a.zip(b).map(|(a, b)| *b - *a).collect() } #[test] fn test_offset_one() { assert_eq!(offset_differences(1, vec![1, 3, 5, 7]), vec![2, 2, 2, -6]); assert_eq!(offset_differences(1, vec![1, 3, 5]), vec![2, 2, -4]); assert_eq!(offset_differences(1, vec![1, 3]), vec![2, -2]); } #[test] fn test_larger_offsets() { assert_eq!(offset_differences(2, vec![1, 3, 5, 7]), vec![4, 4, -4, -4]); assert_eq!(offset_differences(3, vec![1, 3, 5, 7]), vec![6, -2, -2, -2]); assert_eq!(offset_differences(4, vec![1, 3, 5, 7]), vec![0, 0, 0, 0]); assert_eq!(offset_differences(5, vec![1, 3, 5, 7]), vec![2, 2, 2, -6]); } #[test] fn test_degenerate_cases() { assert_eq!(offset_differences(1, vec![0]), vec![0]); assert_eq!(offset_differences(1, vec![1]), vec![0]); let empty: Vec<i32> = vec![]; assert_eq!(offset_differences(1, empty), vec![]); }
ã¢ãžã¥ãŒã«
segment outline
ã¢ãžã¥ãŒã«
impl ãããã¯ã䜿ããšã颿°ãåã«çŽã¥ããŠåå空éåã§ããããšãèŠãŠããŸããã
åæ§ã«ãmod ã䜿ããšãåãšé¢æ°ãåå空éåã§ããŸãã
// Copyright 2023 Google LLC // SPDX-License-Identifier: Apache-2.0 mod foo { pub fn do_something() { println!("foo ã¢ãžã¥ãŒã«å "); } } mod bar { pub fn do_something() { println!("bar ã¢ãžã¥ãŒã«å "); } } fn main() { foo::do_something(); bar::do_something(); }
- ããã±ãŒãžã¯æ©èœãæäŸãã1 å以äžã®ã¯ã¬ãŒãã®ãŸãšãŸããã©ã®ããã«ãã«ãããããèšè¿°ãã
Cargo.tomlãã¡ã€ã«ãå«ã¿ãŸãã - ã¯ã¬ãŒãã¯ã¢ãžã¥ãŒã«ã®æšæ§é ã§ããããã€ããªã¯ã¬ãŒãã¯å®è¡ãã¡ã€ã«ãäœæããã©ã€ãã©ãªã¯ã¬ãŒãã¯ã©ã€ãã©ãªã«ã³ã³ãã€ã«ãããŸãã
- ã¢ãžã¥ãŒã«ã¯æ§æãšã¹ã³ãŒããå®çŸ©ãããã®ã»ã¯ã·ã§ã³ã®äžå¿ãšãªãæŠå¿µã§ãã
ãã¡ã€ã«ã·ã¹ãã éå±€
ã¢ãžã¥ãŒã«ã®å 容ãçç¥ãããšãRust ã¯ãããå¥ã®ãã¡ã€ã«å ã§æ¢ããŸã:
// Copyright 2022 Google LLC // SPDX-License-Identifier: Apache-2.0 mod garden;
ããã«ãããgarden ã¢ãžã¥ãŒã«ã®å
容ã src/garden.rs ã«ããããšã Rust ã«äŒããŸãã åæ§ã«ãgarden::vegetables ã¢ãžã¥ãŒã«ã¯ src/garden/vegetables.rs ã«ãããŸãã
crate ã«ãŒãã¯æ¬¡ã®å Žæã«ãããŸã:
src/lib.rsïŒã©ã€ãã©ãª crate ã®å ŽåïŒsrc/main.rsïŒãã€ã㪠crate ã®å ŽåïŒ
ãã¡ã€ã«å ã§å®çŸ©ãããã¢ãžã¥ãŒã«ãããå éšããã¥ã¡ã³ãã³ã¡ã³ããã䜿ã£ãŠææžåã§ããŸãã ãããã¯ããããå«ãã¢ã€ãã ãææžåããŸãããã®å Žåã¯ã¢ãžã¥ãŒã«ã§ãã
// Copyright 2022 Google LLC // SPDX-License-Identifier: Apache-2.0 //! ãã®ã¢ãžã¥ãŒã«ã¯ garden ãå®è£ ããŠããã髿§èœãªçºèœå®è£ ãå«ã¿ãŸãã // ãã®ã¢ãžã¥ãŒã«ããåãåãšã¯ã¹ããŒãããŸãã pub use garden::Garden; pub use seeds::SeedPacket; /// æå®ããã seed packet ããŸããŸãã pub fn sow(seeds: Vec<SeedPacket>) { todo!() } /// æºåãã§ããŠãã garden å ã®åç©«ç©ãåç©«ããŸãã pub fn harvest(garden: &mut Garden) { todo!() }
-
Rust 2018 ããåã¯ãã¢ãžã¥ãŒã«ã¯
module.rsã§ã¯ãªãmodule/mod.rsã«é 眮ããå¿ èŠããããŸããããã㯠2018 以éã® edition ã§ãåŒãç¶ãæå¹ãªä»£æ¿ææ®µã§ãã -
filename/mod.rsã®ä»£ããã«filename.rsãå°å ¥ãããäž»ãªçç±ã¯ãmod.rsãšããååã®ãã¡ã€ã«ã倿°ãããšãIDE ã§åºå¥ãã«ãããªãããã§ãã -
ã¡ã€ã³ã¢ãžã¥ãŒã«ããã¡ã€ã«ã§ãã£ãŠããããæ·±ããã¹ãã§ã¯ãã©ã«ããŒã䜿çšã§ããŸã:
src/ âââ main.rs âââ top_module.rs âââ top_module/ âââ sub_module.rs -
Rust ãã¢ãžã¥ãŒã«ãæ¢ãå Žæã¯ãã³ã³ãã€ã©ãã£ã¬ã¯ãã£ãã§å€æŽã§ããŸã:
// Copyright 2022 Google LLC // SPDX-License-Identifier: Apache-2.0 #[path = "some/path.rs"] mod some_module;ããã¯ãããšãã° Go ã®æ £ç¿ã«äŒŒããŠãã¢ãžã¥ãŒã«ã®ãã¹ãã
some_module_test.rsãšããååã®ãã¡ã€ã«ã«é 眮ãããå Žåã«äŸ¿å©ã§ãã
å¯èŠæ§
ã¢ãžã¥ãŒã«ã¯ãã©ã€ãã·ãŒå¢çã§ã:
- ã¢ãžã¥ãŒã«ã®ã¢ã€ãã ã¯ããã©ã«ãã§éå ¬éã§ãïŒå®è£ ã®è©³çްãé ããŸãïŒã
- 芪ããã³å åŒã®ã¢ã€ãã ã¯åžžã«å¯èŠã§ãã
- èšãæãããšãããã¢ã€ãã ãã¢ãžã¥ãŒã«
fooã§å¯èŠã§ããã°ããã®ã¢ã€ãã ã¯fooã®ãã¹ãŠã®åå«ã§ãå¯èŠã§ãã
// Copyright 2022 Google LLC // SPDX-License-Identifier: Apache-2.0 mod outer { fn private() { println!("outer::private"); } pub fn public() { println!("outer::public"); } mod inner { fn private() { println!("outer::inner::private"); } pub fn public() { println!("outer::inner::public"); super::private(); } } } fn main() { outer::public(); }
- ã¢ãžã¥ãŒã«ãå
¬éããã«ã¯
pubããŒã¯ãŒãã䜿çšããŸãã
ããã«ãå
¬éç¯å²ãå¶éããããã®é«åºŠãª pub(...) æå®åããããŸãã
- Rust Reference ãåç §ããŠãã ããã
pub(crate)ã®å¯èŠæ§ãèšå®ããã®ã¯äžè¬çãªãã¿ãŒã³ã§ãã- ããŸãäžè¬çã§ã¯ãããŸããããç¹å®ã®ãã¹ã«å¯èŠæ§ãäžããããšãã§ããŸãã
- ãããã®å Žåããå¯èŠæ§ã¯ç¥å ã¢ãžã¥ãŒã«ïŒããã³ãã®ãã¹ãŠã® åå«ïŒã«å¯ŸããŠä»äžãããŠããå¿ èŠããããŸãã
å¯èŠæ§ãšã«ãã»ã«å
ã¢ãžã¥ãŒã«å ã®ã¢ã€ãã ãšåæ§ã«ãstruct ã®ãã£ãŒã«ããããã©ã«ãã§ã¯éå ¬éã§ããéå ¬éãã£ãŒã«ããåæ§ã«ããã®ã¢ãžã¥ãŒã«ã®ä»ã®éšåïŒåã¢ãžã¥ãŒã«ãå«ãïŒããã¯åç §ã§ããŸããããã«ãããstruct ã®å®è£ 詳现ãã«ãã»ã«åããå€éšããèŠããããŒã¿ãæ©èœãå¶åŸ¡ã§ããŸãã
// Copyright 2024 Google LLC // SPDX-License-Identifier: Apache-2.0 use outer::Foo; mod outer { pub struct Foo { pub val: i32, is_big: bool, } impl Foo { pub fn new(val: i32) -> Self { Self { val, is_big: val > 100 } } } pub mod inner { use super::Foo; pub fn print_foo(foo: &Foo) { println!("Is {} big? {}", foo.val, foo.is_big); } } } fn main() { let foo = Foo::new(42); println!("foo.val = {}", foo.val); // let foo = Foo { val: 42, is_big: true }; outer::inner::print_foo(&foo); // println!("Is {} big? {}", foo.val, foo.is_big); }
-
ãã®ã¹ã©ã€ãã§ã¯ãstruct ã«ãããå¯èŠæ§ãã¢ãžã¥ãŒã«åäœã§æ±ºãŸãããšã瀺ããŠããŸãããªããžã§ã¯ãæåèšèªã«æ £ããåè¬è ã¯ãåãã«ãã»ã«åã®å¢çã§ããããšã«æ £ããŠãããããããŸããããã®ããããã®ã¹ã©ã€ã㯠Rust ã®æ¯ãèãããããšã¯ç°ãªãããšã瀺ãã€ã€ãããã§ãã«ãã»ã«åãå®çŸã§ããããšã瀺ããŠããŸãã
-
is_bigãã£ãŒã«ããFooã«ãã£ãŠå®å šã«å¶åŸ¡ãããŠããç¹ã«æ³šç®ããŠãã ãããããã«ãããFooã¯ãã®åæåæ¹æ³ãå¶åŸ¡ããå¿ èŠãªäžå€æ¡ä»¶ïŒããšãã°ãval > 100ã®å Žåã«ã®ã¿is_bigãtrueã«ãªãããšïŒã匷å¶ã§ããŸãã -
åã®éå ¬éãã£ãŒã«ããéå ¬éã¡ãœããã«ã¢ã¯ã»ã¹ããããã«ãåãã¢ãžã¥ãŒã«å ïŒåã¢ãžã¥ãŒã«ãå«ãïŒã§ãã«ããŒé¢æ°ãå®çŸ©ã§ããããšãææããŠãã ããã
-
æåã®ã³ã¡ã³ãã¢ãŠããããè¡ã¯ãéå ¬éãã£ãŒã«ããæã€ struct ãåæåã§ããªãããšã瀺ããŠããŸãã2 ã€ç®ã¯ãéå ¬éãã£ãŒã«ãã«çŽæ¥ã¢ã¯ã»ã¹ããããšãã§ããªãããšã瀺ããŠããŸãã
-
enumã§ã¯å¯èŠæ§ãèšå®ã§ããŸãããããªã¢ã³ããšããã®ããªã¢ã³ãå ã®ããŒã¿ã¯åžžã«å ¬éã§ãã
ããã«åŠã¶ã«ã¯
-
enumã«ãããå¯èŠæ§ïŒãããã¯ãã®æ¬ åŠïŒã«ã€ããŠããã«ç¥ããããåè¬è ãããã°ã#[doc_hidden]ãš#[non_exhaustive]ãåãäžããããããenumã§ã§ããããšãã©ã®ããã«å¶éããããã«äœ¿ããããã瀺ããŸãã -
ä»ã®ã¢ãžã¥ãŒã«ã«
implãããã¯ãããå Žåã§ããã¢ãžã¥ãŒã«ã®å¯èŠæ§ã¯åŒãç¶ãé©çšãããŸã(playground ã®äŸ)ã
useãsuperãself
ã¢ãžã¥ãŒã«ã¯ãuse ã䜿ã£ãŠå¥ã®ã¢ãžã¥ãŒã«ã®ã·ã³ãã«ãã¹ã³ãŒãã«åã蟌ããŸããéåžžãåã¢ãžã¥ãŒã«ã®å
é ã«ã¯æ¬¡ã®ãããªãã®ããããŸãã
// Copyright 2022 Google LLC // SPDX-License-Identifier: Apache-2.0 use std::collections::HashSet; use std::process::abort;
ãã¹
ãã¹ã¯æ¬¡ã®ããã«è§£æ±ºãããŸãã
-
çžå¯Ÿãã¹ãšããŠ:
fooãŸãã¯self::fooã¯ãçŸåšã®ã¢ãžã¥ãŒã«å ã®fooãåç §ããŸããsuper::fooã¯ã芪ã¢ãžã¥ãŒã«å ã®fooãåç §ããŸãã
-
絶察ãã¹ãšããŠ:
crate::fooã¯ãçŸåšã®ã¯ã¬ãŒãã®ã«ãŒãã«ããfooãåç §ããŸããbar::fooã¯ãbarã¯ã¬ãŒãå ã®fooãåç §ããŸãã
-
ã·ã³ãã«ãããçããã¹ã§ãåãšã¯ã¹ããŒããããã®ã¯äžè¬çã§ããããšãã°ãã¯ã¬ãŒãã®æäžäœã®
lib.rsã«ã¯æ¬¡ã®ãããªèšè¿°ããããããããŸããã// Copyright 2022 Google LLC // SPDX-License-Identifier: Apache-2.0 mod storage; pub use storage::disk::DiskStorage; pub use storage::network::NetworkStorage;ããã«ããã
DiskStorageãšNetworkStorageã¯ã䟿å©ã§çããã¹ã§ä»ã®ã¯ã¬ãŒãããå©çšã§ããããã«ãªããŸãã -
ã»ãšãã©ã®å Žåã
useããå¿ èŠãããã®ã¯ããã®ã¢ãžã¥ãŒã«å ã«çŸããã¢ã€ãã ã ãã§ãããã ãããããã¬ã€ãã®ã¡ãœãããåŒã³åºãã«ã¯ããã®ãã¬ã€ããå®è£ ããŠããåããã§ã«ã¹ã³ãŒãå ã«ãã£ããšããŠãããã®ãã¬ã€ãèªäœãã¹ã³ãŒãå ã«ãªããã°ãªããŸãããããšãã°ãReadãã¬ã€ããå®è£ ããŠããåã§read_to_stringã¡ãœããã䜿ãã«ã¯ãuse std::io::Readãå¿ èŠã§ãã -
useæã§ã¯ã¯ã€ã«ãã«ãŒãã䜿ããŸã:use std::io::*ãããã¯ãã©ã®ã¢ã€ãã ãã€ã³ããŒããããã®ããæç¢ºã§ãªããããããå°æ¥å€ããå¯èœæ§ããããããæšå¥šãããŸããã
æŒç¿: GUI ã©ã€ãã©ãªã®ã¢ãžã¥ãŒã«
ãã®æŒç¿ã§ã¯ãå°ã㪠GUI ã©ã€ãã©ãªå®è£
ãåç·šæããŸãããã® ã©ã€ãã©ãªã¯ Widget ãã¬ã€ããšããã®ãã¬ã€ãã®ããã€ãã®å®è£
ãããã³ main 颿°ãå®çŸ©ããŠããŸãã
éåžžã¯ãååãŸãã¯å¯æ¥ã«é¢é£ããåã®éåããšã«å°çšã® ã¢ãžã¥ãŒã«ãçšæãããããåãŠã£ãžã§ããåãããããå°çšã®ã¢ãžã¥ãŒã«ã æã€ã¹ãã§ãã
Cargo ã®ã»ããã¢ãã
Rust playground 㯠1 ã€ã®ãã¡ã€ã«ãããµããŒãããŠããªããããããŒã«ã«ã® ãã¡ã€ã«ã·ã¹ãã äžã« Cargo ãããžã§ã¯ããäœæããå¿ èŠããããŸã:
cargo init gui-modules
cd gui-modules
cargo run
çæããã src/main.rs ãç·šéã㊠mod æã远å ããsrc ãã£ã¬ã¯ããªã«è¿œå ã®ãã¡ã€ã«ãäœæããŠãã ããã
ãœãŒã¹
以äžã¯ãGUI ã©ã€ãã©ãªã®åäžã¢ãžã¥ãŒã«å®è£ ã§ã:
// Copyright 2023 Google LLC // SPDX-License-Identifier: Apache-2.0 pub trait Widget { /// Natural width of `self`. fn width(&self) -> usize; /// Draw the widget into a buffer. fn draw_into(&self, buffer: &mut dyn std::fmt::Write); /// Draw the widget on standard output. fn draw(&self) { let mut buffer = String::new(); self.draw_into(&mut buffer); println!("{buffer}"); } } pub struct Label { label: String, } impl Label { fn new(label: &str) -> Label { Label { label: label.to_owned() } } } pub struct Button { label: Label, } impl Button { fn new(label: &str) -> Button { Button { label: Label::new(label) } } } pub struct Window { title: String, widgets: Vec<Box<dyn Widget>>, } impl Window { fn new(title: &str) -> Window { Window { title: title.to_owned(), widgets: Vec::new() } } fn add_widget(&mut self, widget: Box<dyn Widget>) { self.widgets.push(widget); } fn inner_width(&self) -> usize { std::cmp::max( self.title.chars().count(), self.widgets.iter().map(|w| w.width()).max().unwrap_or(0), ) } } impl Widget for Window { fn width(&self) -> usize { // Add 4 paddings for borders self.inner_width() + 4 } fn draw_into(&self, buffer: &mut dyn std::fmt::Write) { let mut inner = String::new(); for widget in &self.widgets { widget.draw_into(&mut inner); } let inner_width = self.inner_width(); // TODO: Change draw_into to return Result<(), std::fmt::Error>. Then use the // ?-operator here instead of .unwrap(). writeln!(buffer, "+-{:-<inner_width$}-+", "").unwrap(); writeln!(buffer, "| {:^inner_width$} |", &self.title).unwrap(); writeln!(buffer, "+={:=<inner_width$}=+", "").unwrap(); for line in inner.lines() { writeln!(buffer, "| {:inner_width$} |", line).unwrap(); } writeln!(buffer, "+-{:-<inner_width$}-+", "").unwrap(); } } impl Widget for Button { fn width(&self) -> usize { self.label.width() + 8 // add a bit of padding } fn draw_into(&self, buffer: &mut dyn std::fmt::Write) { let width = self.width(); let mut label = String::new(); self.label.draw_into(&mut label); writeln!(buffer, "+{:-<width$}+", "").unwrap(); for line in label.lines() { writeln!(buffer, "|{:^width$}|", &line).unwrap(); } writeln!(buffer, "+{:-<width$}+", "").unwrap(); } } impl Widget for Label { fn width(&self) -> usize { self.label.lines().map(|line| line.chars().count()).max().unwrap_or(0) } fn draw_into(&self, buffer: &mut dyn std::fmt::Write) { writeln!(buffer, "{}", &self.label).unwrap(); } } fn main() { let mut window = Window::new("Rust GUI Demo 1.23"); window.add_widget(Box::new(Label::new("This is a small text GUI demo."))); window.add_widget(Box::new(Button::new("Click me!"))); window.draw(); }
åŠçã«ã¯ãèªåã«ãšã£ãŠèªç¶ã ãšæãããã圢ã§ã³ãŒããåå²ããããä¿ãã å¿
èŠãª modãuseãpub 宣èšã«æ
£ããŠããã£ãŠãã ããããã®åŸã ã©ã®ãããªæ§æãæãæ
£çšçããè°è«ããŠãã ããã
è§£ç
src
âââ main.rs
âââ widgets
â  âââ button.rs
â  âââ label.rs
â  âââ window.rs
âââ widgets.rs
// èäœæš© 2023 Google LLC
// SPDX-License-Identifier: Apache-2.0
// ---- src/widgets.rs ----
pub use button::Button;
pub use label::Label;
pub use window::Window;
mod button;
mod label;
mod window;
pub trait Widget {
/// `self` ã®èªç¶å¹
ã
fn width(&self) -> usize;
/// ãŠã£ãžã§ããããããã¡ã«æç»ããŸãã
fn draw_into(&self, buffer: &mut dyn std::fmt::Write);
/// ãŠã£ãžã§ãããæšæºåºåã«æç»ããŸãã
fn draw(&self) {
let mut buffer = String::new();
self.draw_into(&mut buffer);
println!("{buffer}");
}
}
// èäœæš© 2023 Google LLC
// SPDX-License-Identifier: Apache-2.0
// ---- src/widgets/label.rs ----
use super::Widget;
pub struct Label {
label: String,
}
impl Label {
pub fn new(label: &str) -> Label {
Label { label: label.to_owned() }
}
}
impl Widget for Label {
fn width(&self) -> usize {
// ANCHOR_END: Label-width
self.label.lines().map(|line| line.chars().count()).max().unwrap_or(0)
}
// ANCHOR: Label-draw_into
fn draw_into(&self, buffer: &mut dyn std::fmt::Write) {
// ANCHOR_END: Label-draw_into
writeln!(buffer, "{}", &self.label).unwrap();
}
}
// èäœæš© 2023 Google LLC
// SPDX-License-Identifier: Apache-2.0
// ---- src/widgets/button.rs ----
use super::{Label, Widget};
pub struct Button {
label: Label,
}
impl Button {
pub fn new(label: &str) -> Button {
Button { label: Label::new(label) }
}
}
impl Widget for Button {
fn width(&self) -> usize {
// ANCHOR_END: Button-width
self.label.width() + 8 // å°ãããã£ã³ã°ã远å ãã
}
// ANCHOR: Button-draw_into
fn draw_into(&self, buffer: &mut dyn std::fmt::Write) {
// ANCHOR_END: Button-draw_into
let width = self.width();
let mut label = String::new();
self.label.draw_into(&mut label);
writeln!(buffer, "+{:-<width$}+", "").unwrap();
for line in label.lines() {
writeln!(buffer, "|{:^width$}|", &line).unwrap();
}
writeln!(buffer, "+{:-<width$}+", "").unwrap();
}
}
// èäœæš© 2023 Google LLC
// SPDX-License-Identifier: Apache-2.0
// ---- src/widgets/window.rs ----
use super::Widget;
pub struct Window {
title: String,
widgets: Vec<Box<dyn Widget>>,
}
impl Window {
pub fn new(title: &str) -> Window {
Window { title: title.to_owned(), widgets: Vec::new() }
}
pub fn add_widget(&mut self, widget: Box<dyn Widget>) {
self.widgets.push(widget);
}
fn inner_width(&self) -> usize {
std::cmp::max(
self.title.chars().count(),
self.widgets.iter().map(|w| w.width()).max().unwrap_or(0),
)
}
}
impl Widget for Window {
fn width(&self) -> usize {
// ANCHOR_END: Window-width
// æ ç·çšã« 4 æååã®ããã£ã³ã°ã远å ãã
self.inner_width() + 4
}
// ANCHOR: Window-draw_into
fn draw_into(&self, buffer: &mut dyn std::fmt::Write) {
// ANCHOR_END: Window-draw_into
let mut inner = String::new();
for widget in &self.widgets {
widget.draw_into(&mut inner);
}
let inner_width = self.inner_width();
// TODO: ãšã©ãŒãã³ããªã³ã°ã«ã€ããŠåŠãã åŸã§ã
// draw_into ã Result<(), std::fmt::Error> ãè¿ãããã«å€æŽã§ããŸãããã®åŸã
// ããã§ã¯ .unwrap() ã®ä»£ããã« ? æŒç®åã䜿ããŸãã
writeln!(buffer, "+-{:-<inner_width$}-+", "").unwrap();
writeln!(buffer, "| {:^inner_width$} |", &self.title).unwrap();
writeln!(buffer, "+={:=<inner_width$}=+", "").unwrap();
for line in inner.lines() {
writeln!(buffer, "| {:inner_width$} |", line).unwrap();
}
writeln!(buffer, "+-{:-<inner_width$}-+", "").unwrap();
}
}
// èäœæš© 2023 Google LLC
// SPDX-License-Identifier: Apache-2.0
// ---- src/main.rs ----
mod widgets;
use widgets::{Button, Label, Widget, Window};
fn main() {
let mut window = Window::new("Rust GUI ã㢠1.23");
window.add_widget(Box::new(Label::new("ããã¯å°ããªããã¹ã GUI ãã¢ã§ãã")));
window.add_widget(Box::new(Button::new("ã¯ãªãã¯ããŠïŒ")));
window.draw();
}
ãã¹ã
segment outline
åäœãã¹ã
Rust ãš Cargo ã«ã¯ãã·ã³ãã«ãªåäœãã¹ããã¬ãŒã ã¯ãŒã¯ãä»å±ããŠããŸãããã¹ãã«ã¯ #[test] ãä»ããŸããåäœãã¹ãã¯ããã¹ãããã tests ã¢ãžã¥ãŒã«ã«çœ®ãããããšãå€ãã #[cfg(test)] ã䜿ã£ãŠããã¹ãããã«ããããšãã«ã ãæ¡ä»¶ä»ãã§ã³ã³ãã€ã«ãããããã«ããŸãã
// èäœæš© 2022 Google LLC // SPDX-License-Identifier: Apache-2.0 fn first_word(text: &str) -> &str { match text.find(' ') { Some(idx) => &text[..idx], None => &text, } } #[cfg(test)] mod tests { use super::*; #[test] fn test_empty() { assert_eq!(first_word(""), ""); } #[test] fn test_single_word() { assert_eq!(first_word("Hello"), "Hello"); } #[test] fn test_multiple_words() { assert_eq!(first_word("Hello World"), "Hello"); } }
- ããã«ãããéå ¬éã®ãã«ããŒãåäœãã¹ãã§ããŸãã
#[cfg(test)]屿§ã¯ãcargo testãå®è¡ãããšãã«ã®ã¿æå¹ã«ãªããŸãã
ãã®ä»ã®çš®é¡ã®ãã¹ã
çµ±åãã¹ã
ã©ã€ãã©ãªãã¯ã©ã€ã¢ã³ããšããŠãã¹ããããå Žåã¯ãçµ±åãã¹ãã䜿çšããŸãã
tests/ ã®äžã« .rs ãã¡ã€ã«ãäœæããŸã:
// Copyright 2023 Google LLC
// SPDX-License-Identifier: Apache-2.0
// tests/my_library.rs
use my_library::init;
#[test]
fn test_init() {
assert!(init().is_ok());
}
ãããã®ãã¹ãããã¢ã¯ã»ã¹ã§ããã®ã¯ãã¯ã¬ãŒãã®å ¬é API ã®ã¿ã§ãã
ããã¥ã¡ã³ããã¹ã
Rust ã«ã¯ããã¥ã¡ã³ããã¹ãã®ãµããŒããçµã¿èŸŒãŸããŠããŸã:
#![allow(unused)] fn main() { // Copyright 2023 Google LLC // SPDX-License-Identifier: Apache-2.0 /// æå®ãããé·ãã«æååãççž®ããŸãã /// /// ``` /// # use playground::shorten_string; /// assert_eq!(shorten_string("Hello World", 5), "Hello"); /// assert_eq!(shorten_string("Hello World", 20), "Hello World"); /// ``` pub fn shorten_string(s: &str, length: usize) -> &str { &s[..std::cmp::min(length, s.len())] } }
///ã³ã¡ã³ãå ã®ã³ãŒããããã¯ã¯ãèªåçã« Rust ã³ãŒããšããŠæ±ãããŸãã- ãã®ã³ãŒãã¯
cargo testã®äžéšãšããŠã³ã³ãã€ã«ããã³å®è¡ãããŸãã - ã³ãŒãå
ã«
#ã远å ãããšãããã¥ã¡ã³ãã§ã¯é衚瀺ã«ãªããŸããã ããã§ãã³ã³ãã€ã«ããã³å®è¡ãããŸãã - äžèšã®ã³ãŒã㯠Rust Playground ã§è©ŠããŠãã ããã
ã³ã³ãã€ã©ã® lint ãš Clippy
Rust ã³ã³ãã€ã©ã¯ãåªãããšã©ãŒã¡ãã»ãŒãžã«å ããŠã圹ç«ã€çµã¿èŸŒã¿ lint ãçæããŸããClippy ã¯ããã«å€ãã® lint ãæäŸãã ãããžã§ã¯ãããšã«æå¹åã§ããã°ã«ãŒãã«æŽçãããŠããŸãã
// Copyright 2023 Google LLC // SPDX-License-Identifier: Apache-2.0 #[deny(clippy::cast_possible_truncation)] fn main() { let mut x = 3; while (x < 70000) { x *= 2; } println!("X probably fits in a u16, right? {}", x as u16); }
ããã§ã¯ã³ã³ãã€ã©ã® lint ã¯è¡šç€ºãããŠããŸãããclippy lint ã¯è¡šç€ºãããŠããŸãããclippy ã®èŠåã衚瀺ããã«ã¯ãplayground ãµã€ãã§ clippy ãå®è¡ããŠãã ãããClippy ã«ã¯ ãã® lint ã«é¢ããåºç¯ãªããã¥ã¡ã³ãããããæ°ãã lintïŒããã©ã«ãã§ deny ããã lint ãå«ãïŒãåžžã«è¿œå ãããŠããŸãã
help: ... ãä»ãããšã©ãŒãèŠåã¯ãcargo fix ãŸã㯠ãšãã£ã¿çµç±ã§ä¿®æ£ã§ããŸãã
æŒç¿: Luhn ã¢ã«ãŽãªãºã
Luhn algorithm ã¯ãã¯ã¬ãžããã«ãŒãçªå·ã æ€èšŒããããã«äœ¿çšãããŸãããã®ã¢ã«ãŽãªãºã ã¯æååãå ¥åãšããŠåãåããã¯ã¬ãžããã«ãŒãçªå·ãæ€èšŒãããã㫠次ã®ããšãè¡ããŸãã
-
ãã¹ãŠã®ç©ºçœãç¡èŠããŸãã2 æ¡æªæºã®æ°åã¯æåŠããŸããæåã ãã®ä»ã®æ°å以å€ã®æåã¯æåŠããŸãã
-
å³ããå·Šãžç§»åããªããã2 ã€ããã®æ°åããã¹ãŠ 2 åããŸããæ°å€
1234ã§ã¯ã3ãš1ã 2 åããŸããæ°å€98765ã§ã¯ã6ãš8ã 2 åããŸãã -
æ°åã 2 åããåŸãçµæã 9 ãã倧ããå Žåã¯ãã®æ¡ãåèšããŸãããããã£ãŠã
7ã 2 åãããš14ã«ãªããããã¯1 + 4 = 5ã«ãªããŸãã -
2 åããŠããªãæ°åãš 2 åããæ°åããã¹ãŠåèšããŸãã
-
åèšã
0ã§çµããå Žåããã®ã¯ã¬ãžããã«ãŒãçªå·ã¯æå¹ã§ãã
æäŸãããŠããã³ãŒãã«ã¯ãLuhn ã¢ã«ãŽãªãºã ã®ãã°ã®ããå®è£ ãšã ã¢ã«ãŽãªãºã ã®å€§éšåãæ£ããå®è£ ãããŠããããšã確èªãã 2 ã€ã®åºæ¬çãªãŠããããã¹ãã å«ãŸããŠããŸãã
以äžã®ã³ãŒãã https://play.rust-lang.org/ ã«ã³ããŒãã远å ã®ãã¹ããäœæã㊠æäŸãããŠããå®è£ ã®ãã°ãæããã«ããèŠã€ãããã°ãä¿®æ£ããŠãã ããã
// èäœæš© 2023 Google LLC // SPDX-License-Identifier: Apache-2.0 pub fn luhn(cc_number: &str) -> bool { let mut sum = 0; let mut double = false; for c in cc_number.chars().rev() { if let Some(digit) = c.to_digit(10) { if double { let double_digit = digit * 2; sum += if double_digit > 9 { double_digit - 9 } else { double_digit }; } else { sum += digit; } double = !double; } else { continue; } } sum % 10 == 0 } #[cfg(test)] mod test { use super::*; #[test] fn test_valid_cc_number() { assert!(luhn("4263 9826 4026 9299")); assert!(luhn("4539 3195 0343 6467")); assert!(luhn("7992 7398 713")); } #[test] fn test_invalid_cc_number() { assert!(!luhn("4223 9826 4026 9299")); assert!(!luhn("4539 3195 0343 6476")); assert!(!luhn("8273 1232 7352 0569")); } }
è§£ç
// èäœæš© 2023 Google LLC // SPDX-License-Identifier: Apache-2.0 pub fn luhn(cc_number: &str) -> bool { let mut sum = 0; let mut double = false; let mut digits = 0; for c in cc_number.chars().rev() { if let Some(digit) = c.to_digit(10) { digits += 1; if double { let double_digit = digit * 2; sum += if double_digit > 9 { double_digit - 9 } else { double_digit }; } else { sum += digit; } double = !double; } else if c.is_whitespace() { // New: accept whitespace. continue; } else { // New: reject all other characters. return false; } } // New: check that we have at least two digits digits >= 2 && sum % 10 == 0 } #[cfg(test)] mod test { use super::*; #[test] fn test_valid_cc_number() { assert!(luhn("4263 9826 4026 9299")); assert!(luhn("4539 3195 0343 6467")); assert!(luhn("7992 7398 713")); } #[test] fn test_invalid_cc_number() { assert!(!luhn("4223 9826 4026 9299")); assert!(!luhn("4539 3195 0343 6476")); assert!(!luhn("8273 1232 7352 0569")); } #[test] fn test_non_digit_cc_number() { assert!(!luhn("foo")); assert!(!luhn("foo 0 0")); } #[test] fn test_empty_cc_number() { assert!(!luhn("")); assert!(!luhn(" ")); assert!(!luhn(" ")); assert!(!luhn(" ")); } #[test] fn test_single_digit_cc_number() { assert!(!luhn("0")); } #[test] fn test_two_digit_cc_number() { assert!(luhn(" 0 0 ")); } }
ãããããªãã
session outline
ãšã©ãŒåŠç
segment outline
ãããã¯
èŽåœçãªã©ã³ã¿ã€ã ãšã©ãŒãçºçãããšãRust ã¯ããããã¯ããçºçãããŸãã
// Copyright 2022 Google LLC // SPDX-License-Identifier: Apache-2.0 fn main() { let v = vec![10, 20, 30]; dbg!(v[100]); }
- ãããã¯ã¯ãå埩äžèœã§äºæããªããšã©ãŒã®ããã®ãã®ã§ãã
- ãããã¯ã¯ããã°ã©ã å ã®ãã°ã®å åã§ãã
- å¢çãã§ãã¯ã®å€±æã®ãããªã©ã³ã¿ã€ã é害ã¯ããããã¯ãåŒãèµ·ããããšããããŸãã
- ã¢ãµãŒã·ã§ã³ïŒ
assert!ãªã©ïŒã¯ã倱æãããšãããã¯ããŸãã - ç¹å®ã®ç®çã§ãããã¯ãããã«ã¯ã
panic!ãã¯ãã䜿ããŸãã
- ãããã¯ãçºçãããšã¹ã¿ãã¯ããã¢ã³ã¯ã€ã³ããããã颿°ã æ»ã£ãå Žåãšåãããã«å€ããããããããŸãã
- ã¯ã©ãã·ã¥ã蚱容ã§ããªãå Žåã¯ããããã¯ããªã APIïŒ
Vec::getãªã©ïŒã䜿çšããŠãã ããã
ããã©ã«ãã§ã¯ããããã¯ãçºçãããšã¹ã¿ãã¯ãã¢ã³ã¯ã€ã³ããããŸããã¢ã³ã¯ã€ã³ãã¯ææã§ããŸãã
// Copyright 2022 Google LLC // SPDX-License-Identifier: Apache-2.0 use std::panic; fn main() { let result = panic::catch_unwind(|| "No problem here!"); dbg!(result); let result = panic::catch_unwind(|| { panic!("oh no!"); }); dbg!(result); }
- ææã¯äžè¬çã§ã¯ãããŸããã
catch_unwindã䜿ã£ãŠ äŸå€ãå®è£ ããããšããªãã§ãã ããã - ããã¯ã1 ã€ã®ãªã¯ãšã¹ããã¯ã©ãã·ã¥ããŠãåäœãç¶ç¶ãã¹ã ãµãŒããŒã§ã¯æçšãªå ŽåããããŸãã
Cargo.tomlã§panic = 'abort'ãèšå®ãããŠããå Žåãããã¯æ©èœããŸããã
Result
Rust ã«ããããšã©ãŒãã³ããªã³ã°ã®äž»èŠãªä»çµã¿ã¯ Result åæåã§ãããããã¯æšæºã©ã€ãã©ãªã®åã«ã€ããŠèª¬æããéã«å°ãèŠãŸããã
// èäœæš© 2022 Google LLC // SPDX-License-Identifier: Apache-2.0 use std::fs::File; use std::io::Read; fn main() { let file: Result<File, std::io::Error> = File::open("diary.txt"); match file { Ok(mut file) => { let mut contents = String::new(); if let Ok(bytes) = file.read_to_string(&mut contents) { println!("芪æãªãæ¥èšãž: {contents} ({bytes} ãã€ã)"); } else { println!("ãã¡ã€ã«ã®å 容ãèªã¿åããŸããã§ãã"); } } Err(err) => { println!("æ¥èšãéããŸããã§ãã: {err}"); } } }
-
Resultã«ã¯ 2 ã€ã®ããªã¢ã³ãããããŸããæåå€ãå«ãOkãšãäœããã®çš®é¡ã®ãšã©ãŒå€ãå«ãErrã§ãã -
颿°ããšã©ãŒãçæããããã©ããã¯ããã®é¢æ°ã
Resultå€ãè¿ãããšã§ã颿°ã®åã·ã°ããã£ã«ãšã³ã³ãŒããããŸãã -
Optionãšåæ§ã«ããšã©ãŒåŠçãå¿ããæ¹æ³ã¯ãããŸãããã©ã¡ãã®ããªã¢ã³ããæã£ãŠãããã確èªããããã«ããŸãResultã«å¯ŸããŠãã¿ãŒã³ãããããªããã°ãæåå€ã«ããšã©ãŒå€ã«ãã¢ã¯ã»ã¹ã§ããŸãããunwrapã®ãããªã¡ãœããã䜿ããšãå ç¢ãªãšã©ãŒãã³ããªã³ã°ãè¡ããªãææ©ãã³ãŒããæžãããããªããŸããããã®ä»£ãããé©åãªãšã©ãŒãã³ããªã³ã°ãã©ãã§çç¥ãããŠããããããœãŒã¹ã³ãŒãäžã§åžžã«ç¢ºèªã§ããŸãã
ããã«è©³ãã
Rust ã®ãšã©ãŒãã³ããªã³ã°ããåè¬è ãä»ã®ããã°ã©ãã³ã°èšèªã§æ £ã芪ããã§ãããããããªããšã©ãŒãã³ããªã³ã°ã®æ £ç¿ãšæ¯èŒãããšãçè§£ã®å©ãã«ãªããããããŸããã
äŸå€
-
å€ãã®èšèªã¯äŸå€ã䜿çšããŸããããšãã°ãC++ãJavaãPython ã§ãã
-
ã»ãšãã©ã®äŸå€ãæã€èšèªã§ã¯ã颿°ãäŸå€ãæããããã©ããã¯ããã®åã·ã°ããã£ã®äžéšãšããŠã¯èŠããŸãããããã¯äžè¬ã«ã颿°ãåŒã³åºããšãã«ããã®é¢æ°ãäŸå€ãæããå¯èœæ§ããããã©ããã倿ã§ããªãããšãæå³ããŸãã
-
äžè¬ã«äŸå€ã¯ã³ãŒã«ã¹ã¿ãã¯ãå·»ãæ»ãã
tryãããã¯ã«å°éãããŸã§äžäœãžäŒæããŸããã³ãŒã«ã¹ã¿ãã¯ã®æ·±ãå Žæã§çºçãããšã©ãŒããããã«äžäœã«ããç¡é¢ä¿ãªé¢æ°ã«åœ±é¿ãäžããå¯èœæ§ããããŸãã
ãšã©ãŒçªå·
-
äžéšã®èšèªã§ã¯ã颿°ã®æåæã®æ»ãå€ãšã¯å¥ã«ããšã©ãŒçªå·ïŒãŸãã¯ãã®ä»ã®ãšã©ãŒå€ïŒãè¿ããŸããäŸãšããŠã¯ C ã Go ããããŸãã
-
èšèªã«ãã£ãŠã¯ãšã©ãŒå€ã®ç¢ºèªãå¿ããããšãããããã®å ŽåãåæåãããŠããªãããããã¯ãã®ä»ã®çç±ã§ç¡å¹ãªæåå€ã«ã¢ã¯ã»ã¹ããŠããŸãå¯èœæ§ããããŸãã
tryæŒç®å
æ¥ç¶æåŠããã¡ã€ã«ãèŠã€ãããªããšãã£ãå®è¡æãšã©ãŒã¯ Result åã§æ±ãããŸã ããåŒã³åºãã®ãã³ã«ãã®åã«å¯ŸããŠãã¿ãŒã³ããããæžãã®ã¯ç
©éã§ãã ãšã©ãŒãåŒã³åºãå
ã«è¿ãã«ã¯ãtryæŒç®å ? ã䜿ããŸããããã«ããã ããããæ¬¡ã®ãããªã³ãŒãã
// èäœæš© 2023 Google LLC
// SPDX-License-Identifier: Apache-2.0
match some_expression {
Ok(value) => value,
Err(err) => return Err(err),
}
ã¯ããã«åçŽãªæ¬¡ã®åœ¢ã«ã§ããŸã
// èäœæš© 2023 Google LLC
// SPDX-License-Identifier: Apache-2.0
some_expression?
ããã䜿ããšããšã©ãŒåŠçã³ãŒããç°¡æœã«ã§ããŸã:
// èäœæš© 2023 Google LLC // SPDX-License-Identifier: Apache-2.0 use std::io::Read; use std::{fs, io}; fn read_username(path: &str) -> Result<String, io::Error> { let username_file_result = fs::File::open(path); let mut username_file = match username_file_result { Ok(file) => file, Err(err) => return Err(err), }; let mut username = String::new(); match username_file.read_to_string(&mut username) { Ok(_) => Ok(username), Err(err) => Err(err), } } fn main() { //fs::write("config.dat", "alice").unwrap(); let username = read_username("config.dat"); println!("username or error: {username:?}"); }
read_username 颿°ãã? ã䜿ãããã«ç°¡ç¥åããŠãã ããã
ãã€ã³ã:
username倿°ã«ã¯ãOk(string)ãŸãã¯Err(error)ã®ãããããå ¥ããŸããfs::writeåŒã³åºãã䜿ã£ãŠããã¡ã€ã«ããªãå Žåã空㮠ãã¡ã€ã«ããŠãŒã¶ãŒåãå ¥ã£ããã¡ã€ã«ãšãã£ãåã·ããªãªã詊ããŠãã ããã- ãªãã
mainã¯std::process::Terminationãå®è£ ããŠããéãResult<(), E>ãè¿ããŸããå®éã«ã¯ãããã¯EãDebugãå®è£ ããŠããããšã æå³ããŸããå®è¡ãã¡ã€ã«ã¯Errããªã¢ã³ãã衚瀺ãããšã©ãŒæã«ã¯ 0 以å€ã®çµäº ã¹ããŒã¿ã¹ãè¿ããŸãã
Try 倿
? ã®å®éã®å±éã¯ããããŸã§ã«ç€ºãããã®ãããå°ãè€éã§ãã
// Copyright 2023 Google LLC
// SPDX-License-Identifier: Apache-2.0
expression?
ããã¯æ¬¡ãšåãããã«åäœããŸãã
// Copyright 2023 Google LLC
// SPDX-License-Identifier: Apache-2.0
match expression {
Ok(value) => value,
Err(err) => return Err(From::from(err)),
}
ããã§ã® From::from åŒã³åºãã¯ããšã©ãŒåã颿°ãè¿ãåã«å€æããããšããããšãæå³ããŸããããã«ããããšã©ãŒãããäžäœã¬ãã«ã®ãšã©ãŒã«ç°¡åã«ã«ãã»ã«åã§ããŸãã
äŸ
// Copyright 2023 Google LLC // SPDX-License-Identifier: Apache-2.0 use std::error::Error; use std::io::Read; use std::{fmt, fs, io}; #[derive(Debug)] enum ReadUsernameError { IoError(io::Error), EmptyUsername(String), } impl Error for ReadUsernameError {} impl fmt::Display for ReadUsernameError { fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { match self { Self::IoError(e) => write!(f, "I/O error: {e}"), Self::EmptyUsername(path) => write!(f, "Found no username in {path}"), } } } impl From<io::Error> for ReadUsernameError { fn from(err: io::Error) -> Self { Self::IoError(err) } } fn read_username(path: &str) -> Result<String, ReadUsernameError> { let mut username = String::with_capacity(100); fs::File::open(path)?.read_to_string(&mut username)?; if username.is_empty() { return Err(ReadUsernameError::EmptyUsername(String::from(path))); } Ok(username) } fn main() { //std::fs::write("config.dat", "").unwrap(); let username = read_username("config.dat"); println!("username or error: {username:?}"); }
? æŒç®åã¯ã颿°ã®æ»ãå€ã®åãšäºææ§ã®ããå€ãè¿ããªããã°ãªããŸãããResult ã®å Žåãããã¯ãšã©ãŒåã«äºææ§ãå¿
èŠã§ããããšãæå³ããŸããResult<T, ErrorOuter> ãè¿ã颿°ã Result<U, ErrorInner> åã®å€ã«å¯Ÿã㊠? ã䜿ããã®ã¯ãErrorOuter ãš ErrorInner ãåãåã§ããããErrorOuter ã From<ErrorInner> ãå®è£
ããŠããå Žåã«éãããŸãã
From å®è£
ã®äžè¬çãªä»£æ¿ææ®µã¯ Result::map_err ã§ãããç¹ã«å€æã 1 ãæã§ããçºçããªãå Žåã«ãã䜿ãããŸãã
Option ã«ã¯äºææ§èŠä»¶ããããŸãããOption<T> ãè¿ã颿°ã¯ãä»»æã® T ãš U ã®åã«ã€ã㊠Option<U> ã«å¯Ÿã㊠? æŒç®åã䜿çšã§ããŸãã
Result ãè¿ã颿°ã¯ Option ã«å¯Ÿã㊠? ã䜿ããããã®éãåæ§ã§ãããã ããOption::ok_or 㯠Option ã Result ã«å€æããResult::ok 㯠Result ã Option ã«å€æããŸãã
åçãªãšã©ãŒå
ãã¹ãŠã®ç°ãªãå¯èœæ§ãç¶²çŸ
ããç¬èªã® enum ãæžããªããŠããä»»æã®åã®ãšã©ãŒãè¿ããããã«ãããå ŽåããããŸããstd::error::Error ãã¬ã€ãã䜿ããšãä»»æã®ãšã©ãŒãä¿æã§ãããã¬ã€ããªããžã§ã¯ããç°¡åã«äœæã§ããŸãã
// Copyright 2023 Google LLC // SPDX-License-Identifier: Apache-2.0 use std::error::Error; use std::fs; use std::io::Read; fn read_count(path: &str) -> Result<i32, Box<dyn Error>> { let mut count_str = String::new(); fs::File::open(path)?.read_to_string(&mut count_str)?; let count: i32 = count_str.parse()?; Ok(count) } fn main() { fs::write("count.dat", "1i3").unwrap(); match read_count("count.dat") { Ok(count) => println!("Count: {count}"), Err(err) => println!("Error: {err}"), } }
read_count 颿°ã¯ãstd::io::ErrorïŒãã¡ã€ã«æäœããïŒãŸã㯠std::num::ParseIntErrorïŒString::parse ããïŒãè¿ãå¯èœæ§ããããŸãã
ãšã©ãŒã Box åãããšã³ãŒãéãæžãããŸããããã®ä»£ããã«ãããã°ã©ã å
ã§ç°ãªããšã©ãŒã±ãŒã¹ãããããæç¢ºã«åŠçããèœåã¯å€±ãããŸãããã®ãããã©ã€ãã©ãªã®å
¬é API ã§ Box<dyn Error> ã䜿ãã®ã¯äžè¬çã«ã¯è¯ãèãã§ã¯ãããŸããããåã«ã©ããã§ãšã©ãŒã¡ãã»ãŒãžã衚瀺ãããã ãã®ããã°ã©ã ã§ã¯ãè¯ãéžæè¢ã«ãªãããŸãã
ã«ã¹ã¿ã ãšã©ãŒåãå®çŸ©ããéã¯ãããã Box åã§ããããã« std::error::Error ãã¬ã€ããå¿
ãå®è£
ããŠãã ããã
thiserror
thiserror ã¯ã¬ãŒãã¯ããšã©ãŒåãå®çŸ©ããéã®å®åçãªã³ãŒããé¿ããã®ã«åœ¹ç«ã€ãã¯ããæäŸããŸããFrom<T>ãDisplayãããã³ Error ãã¬ã€ãã®å®è£
ãæ¯æŽãã derive ãã¯ããæäŸããŸãã
// èäœæš© 2024 Google LLC // SPDX-License-Identifier: Apache-2.0 use std::io::Read; use std::{fs, io}; use thiserror::Error; #[derive(Debug, Error)] enum ReadUsernameError { #[error("I/O error: {0}")] IoError(#[from] io::Error), #[error("Found no username in {0}")] EmptyUsername(String), } fn read_username(path: &str) -> Result<String, ReadUsernameError> { let mut username = String::with_capacity(100); fs::File::open(path)?.read_to_string(&mut username)?; if username.is_empty() { return Err(ReadUsernameError::EmptyUsername(String::from(path))); } Ok(username) } fn main() { //fs::write("config.dat", "").unwrap(); match read_username("config.dat") { Ok(username) => println!("Username: {username}"), Err(err) => println!("Error: {err}"), } }
Errorderive ãã¯ãã¯thiserrorã«ãã£ãŠæäŸãããŠãããã³ã³ãã¯ããªæ¹æ³ã§ãšã©ãŒåãå®çŸ©ããã®ã«åœ¹ç«ã€å€ãã®äŸ¿å©ãªå±æ§ãåããŠããŸãã#[error]ã®ã¡ãã»ãŒãžã¯Displayãã¬ã€ãã derive ããããã«äœ¿çšãããŸãã- ïŒ
thiserror::ïŒErrorderive ãã¯ãã¯ãïŒstd::error::ïŒErrorãã¬ã€ããå®è£ ãã广ããããŸããããããšåããã®ã§ã¯ãããŸããããã¬ã€ããšãã¯ãã¯åå空éãå ±æããŸããã
anyhow
anyhow ã¯ã¬ãŒãã¯ã远å ã®ã³ã³ããã¹ãæ
å ±ãä¿æã§ãããªãããªãšã©ãŒåãæäŸããŸããããã¯ããšã©ãŒã«è³ããŸã§ããã°ã©ã ãäœãããŠãããã®æå³çãªãã¬ãŒã¹ãæäŸããããã«äœ¿çšã§ããŸãã
ããã thiserror ã®äŸ¿å©ãªãã¯ããšçµã¿åãããããšã§ãã«ã¹ã¿ã ãšã©ãŒåã«å¯Ÿãããã¬ã€ãå®è£
ãæç€ºçã«æžãå¿
èŠãé¿ããããŸãã
// Copyright 2024 Google LLC // SPDX-License-Identifier: Apache-2.0 use anyhow::{Context, Result, bail}; use std::fs; use std::io::Read; use thiserror::Error; #[derive(Clone, Debug, Eq, Error, PartialEq)] #[error("Found no username in {0}")] struct EmptyUsernameError(String); fn read_username(path: &str) -> Result<String> { let mut username = String::with_capacity(100); fs::File::open(path) .with_context(|| format!("Failed to open {path}"))? .read_to_string(&mut username) .context("Failed to read")?; if username.is_empty() { bail!(EmptyUsernameError(path.to_string())); } Ok(username) } fn main() { //fs::write("config.dat", "").unwrap(); match read_username("config.dat") { Ok(username) => println!("Username: {username}"), Err(err) => println!("Error: {err:?}"), } }
anyhow::Errorã¯æ¬è³ªçã«ã¯Box<dyn Error>ã®ã©ãããŒã§ãããã®ããããããäžè¬ã«ã©ã€ãã©ãªã®å ¬é API ã«ã¯ããŸãé©ããéžæè¢ã§ã¯ãããŸããããã¢ããªã±ãŒã·ã§ã³ã§ã¯åºã䜿ãããŠããŸããanyhow::Result<V>ã¯Result<V, anyhow::Error>ã®åãšã€ãªã¢ã¹ã§ããanyhow::ErrorãæäŸããæ©èœã¯ Go éçºè ã«ã¯ãªãã¿ããããããããŸããããã㯠Go ã®erroråã«äŒŒãæ¯ãèããæäŸããResult<T, anyhow::Error>㯠Go ã®(T, error)ã«ãã䌌ãŠããŸãïŒãã ãããã¢ã®èŠçŽ ã®ãã¡æå³ãæã€ã®ã¯çæ¹ã ããšããæ £ç¿ããããŸãïŒãanyhow::Contextã¯æšæºã®Resultåããã³Optionåã«å¯ŸããŠå®è£ ãããŠãããã¬ã€ãã§ãããããã®åã§.context()ãš.with_context()ãæå¹ã«ããã«ã¯use anyhow::Contextãå¿ èŠã§ãã
ããã«èª¿ã¹ãã«ã¯
anyhow::Errorã¯std::any::Anyãšåæ§ã«ããŠã³ãã£ã¹ãããµããŒãããŠããŸããå¿ èŠã§ããã°ãå éšã«æ ŒçŽãããŠããå ·äœçãªãšã©ãŒåãåãåºããŠèª¿ã¹ãããšãã§ããŸããããã«ã¯Error::downcastã䜿çšããŸãã
æŒç¿: Result ã䜿ã£ãæžãæã
ãã®æŒç¿ã§ã¯ã2æ¥ç®ã«è¡ã£ãåŒè©äŸ¡åšã®æŒç¿ãå蚪ããŸããæåã®è§£æ³ã§ã¯ã èµ·ãããããšã©ãŒã±ãŒã¹ãã€ãŸã 0 ã«ããé€ç®ãç¡èŠããŠããŸãããã®ãšã©ãŒã±ãŒã¹ã æ±ããçºçãããšãã«ãšã©ãŒãè¿ããããeval ãæ
£çšçãªãšã©ãŒãã³ããªã³ã°ã çšããåœ¢ã«æžãæããŠãã ãããeval ã®ãšã©ãŒåãšããŠäœ¿çšããããã®ã·ã³ãã«ãª DivideByZeroError åãçšæããŠããŸãã
// Copyright 2023 Google LLC // SPDX-License-Identifier: Apache-2.0 /// An operation to perform on two subexpressions. #[derive(Debug)] enum Operation { Add, Sub, Mul, Div, } /// An expression, in tree form. #[derive(Debug)] enum Expression { /// An operation on two subexpressions. Op { op: Operation, left: Box<Expression>, right: Box<Expression> }, /// A literal value Value(i64), } #[derive(PartialEq, Eq, Debug)] struct DivideByZeroError; // The original implementation of the expression evaluator. Update this to // return a `Result` and produce an error when dividing by 0. fn eval(e: Expression) -> i64 { match e { Expression::Op { op, left, right } => { let left = eval(*left); let right = eval(*right); match op { Operation::Add => left + right, Operation::Sub => left - right, Operation::Mul => left * right, Operation::Div => if right != 0 { left / right } else { panic!("Cannot divide by zero!"); }, } } Expression::Value(v) => v, } } #[cfg(test)] mod test { use super::*; #[test] fn test_error() { assert_eq!( eval(Expression::Op { op: Operation::Div, left: Box::new(Expression::Value(99)), right: Box::new(Expression::Value(0)), }), Err(DivideByZeroError) ); } #[test] fn test_ok() { let expr = Expression::Op { op: Operation::Sub, left: Box::new(Expression::Value(20)), right: Box::new(Expression::Value(10)), }; assert_eq!(eval(expr), Ok(10)); } }
- ããã§ã®éå§ã³ãŒãã¯ãåã®æŒç¿ã®è§£çãšãŸã£ããåãã§ã¯ãããŸããã ãšã©ãŒã±ãŒã¹ãã©ãã«ããããåŠçã«ç€ºããããæç€ºç㪠panic ã远å ããŠããŸãã åŠçãæ··ä¹±ããŠããå Žåã¯ããã®ç¹ãææããŠãã ããã
è§£ç
// èäœæš© 2023 Google LLC // SPDX-License-Identifier: Apache-2.0 /// An operation to perform on two subexpressions. #[derive(Debug)] enum Operation { Add, Sub, Mul, Div, } /// An expression, in tree form. #[derive(Debug)] enum Expression { /// An operation on two subexpressions. Op { op: Operation, left: Box<Expression>, right: Box<Expression> }, /// A literal value Value(i64), } #[derive(PartialEq, Eq, Debug)] struct DivideByZeroError; fn eval(e: Expression) -> Result<i64, DivideByZeroError> { match e { Expression::Op { op, left, right } => { let left = eval(*left)?; let right = eval(*right)?; Ok(match op { Operation::Add => left + right, Operation::Sub => left - right, Operation::Mul => left * right, Operation::Div => { if right == 0 { return Err(DivideByZeroError); } else { left / right } } }) } Expression::Value(v) => Ok(v), } } #[cfg(test)] mod test { use super::*; #[test] fn test_error() { assert_eq!( eval(Expression::Op { op: Operation::Div, left: Box::new(Expression::Value(99)), right: Box::new(Expression::Value(0)), }), Err(DivideByZeroError) ); } #[test] fn test_ok() { let expr = Expression::Op { op: Operation::Sub, left: Box::new(Expression::Value(20)), right: Box::new(Expression::Value(10)), }; assert_eq!(eval(expr), Ok(10)); } }
Resultã®æ»ãå€å: 颿°ã·ã°ããã£ã¯Result<i64, DivideByZeroError>ãè¿ãããã«å€æŽãããŸãããã®æç€ºç㪠åã·ã°ããã£ã«ãããåŒã³åºãåŽã¯å€±æã®å¯èœæ§ãåŠçããããšã匷å¶ãããŸãã?æŒç®å: ååž°åŒã³åºãã«å¯ŸããŠ?ã䜿çšããŸã:eval(*left)?ãããã«ããã ãšã©ãŒããã£ãããšäŒæãããŸããevalãErrãè¿ããå Žåã颿°ã¯å³åº§ã« ãã®Errãè¿ããŸããOk(v)ãè¿ããå Žåã¯ãvãleftïŒãŸãã¯rightïŒã«ä»£å ¥ãããŸããOkã§ã®ã©ãã: æåããçµæã¯Ok(...)ã§ã©ããããå¿ èŠããããŸãã- ãŒãé€ç®ã®åŠç:
right == 0ãæç€ºçã«ãã§ãã¯ããErr(DivideByZeroError)ãè¿ããŸããããã«ãããå ã®ã³ãŒãã§ã® panic ã眮ãæããããŸãã
DivideByZeroErrorã¯ãŠãããæ§é äœïŒãã£ãŒã«ããªãïŒã§ããããšã©ãŒã«ã€ã㊠远å ã§æäŸããã³ã³ããã¹ãããªããããããã§ã¯ããã§ååã§ããããšã«è§ŠããŠãã ããã?ã«ããããšã©ãŒåŠçãäŸå€ã«ã»ãŒå¹æµããã»ã©ç°¡æœã«ãªãäžæ¹ã§ã å¶åŸ¡ãããŒã¯æç€ºçãªãŸãŸã§ããããšã説æããŠãã ããã
Unsafe Rust
segment outline
Unsafe Rust
Rust èšèªã¯ 2 ã€ã®éšåããæããŸãã
- Safe Rust: ã¡ã¢ãªå®å šã§ãæªå®çŸ©åäœã¯çºçããŸããã
- Unsafe Rust: äºåæ¡ä»¶ã«éåãããšãæªå®çŸ©åäœãåŒãèµ·ããå¯èœæ§ããããŸãã
ãã®ã³ãŒã¹ã§ã¯äž»ã« safe Rust ãèŠãŠããŸããããUnsafe Rust ãäœã§ããããç¥ã£ãŠããããšã¯éèŠã§ãã
unsafe ã³ãŒãã¯å°ããåé¢ãããŠããã¹ãã§ããããã®æ£ããã¯ æ³šææ·±ãææžåãããŠããªããã°ãªããŸããããŸããå®å šãªæœè±¡åã¬ã€ã€ãŒã§ ã©ããããã¹ãã§ãã
Unsafe Rust ã§ã¯ã次㮠5 ã€ã®æ°ããæ©èœã«ã¢ã¯ã»ã¹ã§ããŸãã
- çãã€ã³ã¿ãããªãã¡ã¬ã³ã¹ããã
- å¯å€ãªéç倿°ã«ã¢ã¯ã»ã¹ãŸãã¯å€æŽããã
unionãã£ãŒã«ãã«ã¢ã¯ã»ã¹ãããextern颿°ãå«ãunsafe颿°ãåŒã³åºããunsafeãã¬ã€ããå®è£ ããã
次ã«ãunsafe ã®æ©èœãç°¡åã«èŠãŠãããŸãã詳ããã¯ã Rust Book ã® 19.1 ç« ããã³ Rustonomicon ãåç §ããŠãã ããã
Unsafe Rust ã¯ããã®ã³ãŒããäžæ£ã§ããããšãæå³ããŸãããããã¯ãéçºè ã ã³ã³ãã€ã©ã®å®å šæ§æ©èœã®äžéšãç¡å¹ã«ããæ£ããã³ãŒããèªåã§æžããªããã° ãªããªãããšãæå³ããŸããã€ãŸããã³ã³ãã€ã©ã¯ Rust ã®ã¡ã¢ãªå®å šæ§ã«ãŒã«ã ãã¯ã匷å¶ããŸããã
çãã€ã³ã¿ã®ããªãã¡ã¬ã³ã¹
ãã€ã³ã¿ãäœæããããšèªäœã¯å®å
šã§ãããããããããªãã¡ã¬ã³ã¹ããã«ã¯ unsafe ãå¿
èŠã§ã:
// Copyright 2023 Google LLC // SPDX-License-Identifier: Apache-2.0 fn main() { let mut x = 10; let p1: *mut i32 = &raw mut x; let p2 = p1 as *const i32; // SAFETY: p1 ãš p2 ã¯ããŒã«ã«å€æ°ãžã®çãã€ã³ã¿ãååŸããŠäœæãããããã // null ã§ã¯ãªããã¢ã©ã€ã³ãããŠãããåäžã®ïŒã¹ã¿ãã¯ã«ïŒç¢ºä¿ããã // ãªããžã§ã¯ããæãããšãä¿èšŒãããŠããŸãã // // çãã€ã³ã¿ãåç §ããŠãããªããžã§ã¯ãã¯é¢æ°å šäœã®ããã çåããããã // çãã€ã³ã¿ãååšããŠããããã ã«è§£æŸãããããšã¯ãããŸããããŸãã // çãã€ã³ã¿ãååšããŠããããã ã¯åç §çµç±ã§ã¢ã¯ã»ã¹ãããã // ä»ã®ã¹ã¬ããããåæã«ã¢ã¯ã»ã¹ãããããšããããŸããã unsafe { dbg!(*p1); *p1 = 6; // C ãšåæ§ã«ã倿Žã¯çãã€ã³ã¿ãéããŠé©åã«èŠ³æž¬ã§ããŸãã dbg!(*p2); } // UNSOUND. ããããŠã¯ãããŸããã /* let r: &i32 = unsafe { &*p1 }; dbg!(r); x = 50; dbg!(r); // åç §ãæãåºåºãªããžã§ã¯ãã¯å€æŽãããŠããŸãããã㯠UB ã§ãã */ }
å unsafe ãããã¯ã«ã€ããŠããã®å
éšã®ã³ãŒããå®è¡ããŠãã unsafe æäœã®å®å
šèŠä»¶ãã©ã®ããã«æºãããŠãããã説æããã³ã¡ã³ããæžãã®ã¯ãããå®è·µã§ãïŒãã㊠Android Rust ã¹ã¿ã€ã«ã¬ã€ãã§ãå¿
é ã§ãïŒã
ãã€ã³ã¿ãããªãã¡ã¬ã³ã¹ããå Žåãããã¯ãã€ã³ã¿ã æå¹ ã§ãªããã°ãªããªãããšãæå³ããŸããã€ãŸã:
- ãã€ã³ã¿ã¯ null ã§ãã£ãŠã¯ãªããŸããã
- ãã€ã³ã¿ã¯ ããªãã¡ã¬ã³ã¹å¯èœ ã§ãªããã°ãªããŸããïŒåäžã®ç¢ºä¿æžã¿ãªããžã§ã¯ãã®å¢çå ã§ïŒã
- ãªããžã§ã¯ããè§£æŸæžã¿ã§ãã£ãŠã¯ãªããŸããã
- åãäœçœ®ãžã®åæã¢ã¯ã»ã¹ããã£ãŠã¯ãªããŸããã
- ãã€ã³ã¿ãåç §ããã£ã¹ãããŠåŸããããã®ã§ããå Žåãåºåºãªããžã§ã¯ãã¯çåããŠããªããã°ãªããããã®ã¡ã¢ãªãžã®ã¢ã¯ã»ã¹ã«åç §ã䜿çšããŠã¯ãªããŸããã
ã»ãšãã©ã®å Žåããã€ã³ã¿ã¯é©åã«ã¢ã©ã€ã³ãããŠããå¿ èŠããããŸãã
ãUNSOUNDãã»ã¯ã·ã§ã³ã¯ãããããçš®é¡ã® UB ãã°ã®äŸã瀺ããŠããŸããçãã€ã³ã¿ã®ããªãã¡ã¬ã³ã¹çµæã«å®æã«åç
§ãåããšãåç
§ãå®éã«ã©ã®ãªããžã§ã¯ããæããŠããã®ãã«ã€ããŠã®ã³ã³ãã€ã©ã®ç¥èãè¿åããŠããŸããŸãããã®çµæãborrow checker 㯠x ãåçµããªãããããã®åç
§ãååšããŠããã«ãããããã x ã倿Žã§ããŠããŸããŸãããã€ã³ã¿ããåç
§ãäœæããã«ã¯ã现å¿ã®æ³šæ ãå¿
èŠã§ãã
å¯å€ãªéç倿°
äžå€ã®éç倿°ãèªã¿åãã®ã¯å®å šã§ã:
// èäœæš© 2023 Google LLC // SPDX-License-Identifier: Apache-2.0 static HELLO_WORLD: &str = "Hello, world!"; fn main() { println!("HELLO_WORLD: {HELLO_WORLD}"); }
ããããå¯å€ãªéç倿°ã®èªã¿æžã㯠unsafe ã§ããè€æ°ã®ã¹ã¬ãããåæãªãã«åæã«ã¢ã¯ã»ã¹ã§ãããã®çµæããŒã¿ç«¶åãçºçãããããã§ãã
å¯å€ãªéç倿°ãå¥å šã«äœ¿çšããã«ã¯ãã³ã³ãã€ã©ã®å©ããªãã«äžŠè¡æ§ã«ã€ããŠèå¯ããå¿ èŠããããŸã:
// èäœæš© 2023 Google LLC // SPDX-License-Identifier: Apache-2.0 static mut COUNTER: u32 = 0; fn add_to_counter(inc: u32) { // SAFETY: `COUNTER` ã«ã¢ã¯ã»ã¹ãããä»ã®ã¹ã¬ããã¯ååšããŸããã unsafe { COUNTER += inc; } } fn main() { add_to_counter(42); // SAFETY: `COUNTER` ã«ã¢ã¯ã»ã¹ãããä»ã®ã¹ã¬ããã¯ååšããŸããã unsafe { dbg!(COUNTER); } }
- ããã§ã®ããã°ã©ã ã¯ãã·ã³ã°ã«ã¹ã¬ããã§ããããå¥å
šã§ããããããRust ã³ã³ãã€ã©ã¯é¢æ°ãåå¥ã«æšè«ããããããã®ããšãåæã«ã¯ã§ããŸããã
unsafeãåãé€ããŠãè€æ°ã®ã¹ã¬ããããå¯å€ãªéç倿°ã«ã¢ã¯ã»ã¹ããããšãæªå®çŸ©åäœã§ãããšã³ã³ãã€ã©ãã©ã®ããã«èª¬æããã確èªããŠã¿ãŠãã ããã - 2024 Rust edition ã§ã¯ããã«èžã¿èŸŒã¿ãåç §çµç±ã§å¯å€ãªéç倿°ã«ã¢ã¯ã»ã¹ããããšãããã©ã«ãã§ãšã©ãŒã«ãªããŸãã
- å¯å€ãªéç倿°ã䜿ãã®ãè¯ãèãã§ããããšã¯ãã£ãã«ãªãã代ããã«å éšå¯å€æ§ã䜿ãã¹ãã§ãã
- ããŒãã¢ãã±ãŒã¿ãå®è£
ããå Žåãäžéšã® C API ãæ±ãå Žåãªã©ãäœã¬ãã«ãª
no_stdã³ãŒãã§ã¯å¿ èŠã«ãªãããšããããŸãããã®å Žåã¯ãåç §ã§ã¯ãªããã€ã³ã¿ã䜿ãã¹ãã§ãã
å ±çšäœ
å ±çšäœã¯ enum ã«äŒŒãŠããŸãããã©ã®ãã£ãŒã«ããæå¹ãã¯èªåã§è¿œè·¡ããå¿ èŠããããŸãã
// Copyright 2023 Google LLC // SPDX-License-Identifier: Apache-2.0 #[repr(C)] union MyUnion { i: u8, b: bool, } fn main() { let u = MyUnion { i: 42 }; println!("int: {}", unsafe { u.i }); println!("bool: {}", unsafe { u.b }); // æªå®çŸ©åäœïŒ }
Rust ã§ã¯ãenum ãããåªããä»£æ¿ææ®µãæäŸãããããå ±çšäœãå¿ èŠã«ãªãããšã¯ãŸãã§ããããã§ã C ã©ã€ãã©ãªã® API ãšããåãããéã«ã¯ããšãã©ãå¿ èŠã«ãªããŸãã
ãã€ãåãå¥ã®åãšããŠåè§£éãããã ãã§ããã°ããããã std::mem::transmute ãŸã㯠zerocopy ã¯ã¬ãŒãã®ãããªå®å
šãªã©ãããŒã 䜿ãããã¯ãã§ãã
unsafe 颿°
æªå®çŸ©åäœãé¿ããããã«å®ããªããã°ãªããªã远å ã®äºåæ¡ä»¶ãããå Žåã颿°ãŸãã¯ã¡ãœãã㯠unsafe ãšããŠããŒã¯ã§ããŸãã
unsafe 颿°ã¯ã次㮠2 ã€ã®å Žæã«ç±æ¥ããããšããããŸãã
unsafeãšããŠå®£èšããã Rust 颿°ãextern "C"ãããã¯å ã® unsafe ãªå€éšé¢æ°ã
次ã«ããã® 2 çš®é¡ã® unsafe 颿°ãèŠãŠãããŸãã
Unsafe Rustã®é¢æ°
æªå®çŸ©åäœãé¿ããããã«ç¹å®ã®äºåæ¡ä»¶ãå¿
èŠãªå Žåã¯ãèªåã®é¢æ°ã unsafe ãšããŠããŒã¯ã§ããŸãã
// Copyright 2025 Google LLC // SPDX-License-Identifier: Apache-2.0 /// äžãããããã€ã³ã¿ãæãå€ãå ¥ãæ¿ããŸãã /// /// # Safety /// /// ãã€ã³ã¿ã¯æå¹ã§ãé©åã«ã¢ã©ã€ã³ãããŠããã颿°åŒã³åºãã®é㯠/// ãã以å€ã®æ¹æ³ã§ã¢ã¯ã»ã¹ãããŠããŠã¯ãªããŸããã unsafe fn swap(a: *mut u8, b: *mut u8) { // SAFETY: åŒã³åºãå ã¯ããã€ã³ã¿ãæå¹ã§é©åã«ã¢ã©ã€ã³ãããŠããã // ã»ãã«ã¢ã¯ã»ã¹ããªãããšãä¿èšŒããŠããŸãã unsafe { let temp = *a; *a = *b; *b = temp; } } fn main() { let mut a = 42; let mut b = 66; // SAFETY: ãããã®ãã€ã³ã¿ã¯åç §ããåŸããããã®ãªã®ã§ãæå¹ã§ã // ã¢ã©ã€ã³ãããŠãããæä»çã§ãªããã°ãªããŸããã unsafe { swap(&mut a, &mut b); } println!("a = {}, b = {}", a, b); }
å®éã«ã¯ãswap 颿°ã§ãã€ã³ã¿ã䜿ãããšã¯ãããŸãã â åç
§ã䜿ãã°å®å
šã«å®è£
ã§ããŸãã
Rust 2021 以åã§ã¯ãunsafe 颿°å
ã§ã¯ unsafe ãããã¯ãªãã§ unsafe ãªã³ãŒãã䜿ããããšã«æ³šæããŠãã ããããã㯠2024 ãšãã£ã·ã§ã³ã§å€æŽãããŸãããå€ããšãã£ã·ã§ã³ã§ã¯ #[deny(unsafe_op_in_unsafe_fn)] ã䜿ã£ãŠãããçŠæ¢ã§ããŸãã远å ããŠãã©ããªãã詊ããŠã¿ãŠãã ããã
unsafe ãªå€éšé¢æ°
unsafe extern ã䜿ããšãRust ããã¢ã¯ã»ã¹ããããã®å€éšé¢æ°ã宣èšã§ããŸãã ããã¯ããããã®æ¯ãèãã«ã€ããŠã³ã³ãã€ã©ãæšè«ããææ®µãæããªããããunsafe ã§ãã extern ãããã¯å
ã§å®£èšããã颿°ã«ã¯ãå®å
šã«äœ¿çšããããã®äºåæ¡ä»¶ããããã©ããã« å¿ããŠãsafe ãŸã㯠unsafe ãä»ããå¿
èŠããããŸã:
// èäœæš© 2025 Google LLC // SPDX-License-Identifier: Apache-2.0 use std::ffi::c_char; unsafe extern "C" { // `abs` ã¯ãã€ã³ã¿ãæ±ãããå®å šæ§ã«é¢ããèŠä»¶ããããŸããã safe fn abs(input: i32) -> i32; /// # Safety /// /// `s` ã¯ãæå¹ãª NUL çµç«¯ C æååãžã®ãã€ã³ã¿ã§ãªããã°ãªããããã®é¢æ°åŒã³åºãã® /// éã¯å€æŽãããŠã¯ãªããŸããã unsafe fn strlen(s: *const c_char) -> usize; } fn main() { println!("C ã«ãã -3 ã®çµ¶å¯Ÿå€: {}", abs(-3)); unsafe { // SAFETY: ããã°ã©ã ã®å®è¡äžãã£ãšæå¹ãª C æååãªãã©ã«ãžã®ãã€ã³ã¿ã // æž¡ããŠããŸãã println!("æååã®é·ã: {}", strlen(c"String".as_ptr())); } }
- Rust ã¯ä»¥åããã¹ãŠã® extern 颿°ã unsafe ãšèŠãªããŠããŸããããRust 1.82 ã§
unsafe externãããã¯ãå°å ¥ãããŠããã¯å€ãããŸããã absã¯å€éšé¢æ° (FFI) ã§ãããããæç€ºçã«safeãšããŒã¯ããªããã°ãªããŸããã å€éšé¢æ°ã®åŒã³åºããåé¡ã«ãªãã®ã¯ããããã®é¢æ°ã Rust ã®ã¡ã¢ãªã¢ãã«ã«éåããã ãã€ã³ã¿æäœãè¡ãå Žåã ãã§ãããäžè¬è«ãšããŠã¯ãã©ã®ãã㪠C 颿°ã§ã ä»»æã®ç¶æ³ã§æªå®çŸ©åäœãèµ·ããããå¯èœæ§ããããŸãã- ãã®äŸã®
"C"㯠ABI ã衚ããŠããŸã; ä»ã® ABI ãå©çšã§ããŸãã - Rust ã®é¢æ°ã·ã°ããã£ã颿°å®çŸ©ã®ãã®ãšäžèŽããŠããããšãæ€èšŒããä»çµã¿ã¯ ãããŸãã â ãããä¿èšŒããã®ã¯ããªãèªèº«ã§ã!
unsafe 颿°ã®åŒã³åºã
å®å šæ§èŠä»¶ãå®ããªããšãã¡ã¢ãªå®å šæ§ãæãªãããŸãïŒ
// Copyright 2025 Google LLC // SPDX-License-Identifier: Apache-2.0 #[derive(Debug)] #[repr(C)] struct KeyPair { pk: [u16; 4], // 8 ãã€ã sk: [u16; 4], // 8 ãã€ã } const PK_BYTE_LEN: usize = 8; fn log_public_key(pk_ptr: *const u16) { let pk: &[u16] = unsafe { std::slice::from_raw_parts(pk_ptr, PK_BYTE_LEN) }; println!("{pk:?}"); } fn main() { let key_pair = KeyPair { pk: [1, 2, 3, 4], sk: [0, 0, 42, 0] }; log_public_key(key_pair.pk.as_ptr()); }
å unsafe ãããã¯ã«ã¯ãå¿
ãå®å
šæ§ã³ã¡ã³ããä»ããŠãã ããããã®ã³ã¡ã³ãã§ã¯ã ã³ãŒããå®éã«å®å
šã§ããçç±ã説æããªããã°ãªããŸããããã®äŸã«ã¯å®å
šæ§ã³ã¡ã³ãããªããå¥å
šã§ã¯ãããŸããã
èŠç¹:
slice::from_raw_partsã®ç¬¬ 2 åŒæ°ã¯ããã€ãæ°ã§ã¯ãªã èŠçŽ æ° ã§ãïŒ ãã®äŸã¯ãããé åã®æ«å°Ÿãè¶ããŠå¥ã®é åã«ãŸã§èªã¿é²ããããšã§ã äºæããªãæåãèµ·ããããšã瀺ããŠããŸãã- ããã¯ããã®ãã€ã³ã¿ã®å°åºå ãšãªã£ãé åã®æ«å°Ÿãè¶ã㊠èªã¿åã£ãŠãããããæªå®çŸ©åäœã§ãã
log_public_key㯠unsafe ã§ããã¹ãã§ãããšããã®ããpk_ptrã¯æªå®çŸ©åäœãé¿ããããã« ç¹å®ã®åææ¡ä»¶ãæºãããŠããªããã°ãªããªãããã§ããæªå®çŸ©åäœãåŒãèµ·ãããã å®å šãªé¢æ°ã¯unsoundãšåŒã°ããŸãããã®å®å šæ§ã«é¢ãã ããã¥ã¡ã³ãã«ã¯äœãšæžãã¹ãã§ããããïŒ- æšæºã©ã€ãã©ãªã«ã¯äœã¬ãã«ãª unsafe 颿°ã倿°å«ãŸããŠããŸããå¯èœãªå Žå㯠å®å šãªä»£æ¿ææ®µãåªå ããŠãã ããïŒ
- æé©åã®ããã« unsafe 颿°ã䜿ãå Žåã¯ããã®å¹æã瀺ããã³ãããŒã¯ã å¿ ã远å ããŠãã ããã
unsafe ãã¬ã€ãã®å®è£
颿°ãšåæ§ã«ãæªå®çŸ©åäœãé¿ããããã«å®è£
ãç¹å®ã®æ¡ä»¶ãä¿èšŒããªããã°ãªããªãå Žåã ãã¬ã€ãã unsafe ãšããŠããŒã¯ã§ããŸãã
ããšãã°ãzerocopy ã¯ã¬ãŒãã«ã¯ã 次ã®ãã㪠unsafe ãã¬ã€ãããããŸãã
// èäœæš© 2023 Google LLC // SPDX-License-Identifier: Apache-2.0 use std::{mem, slice}; /// ... /// # Safety /// ãã®åã¯ã衚çŸãå®çŸ©ãããŠãããããã£ã³ã°ãå«ãã§ã¯ãªããŸããã pub unsafe trait IntoBytes { fn as_bytes(&self) -> &[u8] { let len = mem::size_of_val(self); let slf: *const Self = self; unsafe { slice::from_raw_parts(slf.cast::<u8>(), len) } } } // SAFETY: `u32` ã¯è¡šçŸãå®çŸ©ãããŠãããããã£ã³ã°ããããŸããã unsafe impl IntoBytes for u32 {}
ãã®ãã¬ã€ãã® Rustdoc ã«ã¯ããã®ãã¬ã€ããå®å
šã«å®è£
ããããã®èŠä»¶ã説æãã # Safety ã»ã¯ã·ã§ã³ãããã¹ãã§ãã
å®éã® IntoBytes ã®å®å
šæ§ã«é¢ããã»ã¯ã·ã§ã³ã¯ããããããããªãé·ãè€éã§ãã
çµã¿èŸŒã¿ã® Send ãã¬ã€ããš Sync ãã¬ã€ã㯠unsafe ãã¬ã€ãã§ãã
å®å šãªFFIã©ãã
Rust ã¯ãforeign function interfaceïŒFFIïŒãä»ããŠé¢æ°ãåŒã³åºãããã®åªãããµããŒããåããŠããŸããããã䜿ã£ãŠãC ãããã£ã¬ã¯ããªå
ã®ãã¡ã€ã«åãèªã¿åããšãã«äœ¿çšãã libc 颿°ã®å®å
šãªã©ãããŒãæ§ç¯ããŸãã
以äžã®ããã¥ã¢ã«ããŒãžãåç §ãããšããã§ãããã
ãŸããstd::ffi ã¢ãžã¥ãŒã«ã«ãç®ãéããŠãã ãããããã«ã¯ããã®æŒç¿ã§å¿
èŠã«ãªãããã€ãã®æåååããããŸãã
| å | ãšã³ã³ãŒã | 䜿ã |
|---|---|---|
str ãš String | UTF-8 | Rust ã«ãããããã¹ãåŠç |
CStr ãš CString | NULçµç«¯æåå | C 颿°ãšã®ããåã |
OsStr ãš OsString | OS åºæ | OS ãšã®ããåã |
ããããã¹ãŠã®åã®éã§å€æãè¡ããŸãã
&strããCString: æ«å°Ÿã®\0æåã®ããã®é åã確ä¿ããå¿ èŠããããŸããCStringãã*const c_char: C 颿°ãåŒã³åºãã«ã¯ãã€ã³ã¿ãå¿ èŠã§ãã*const c_charãã&CStr: æ«å°Ÿã®\0æåãèŠã€ãããããã®ãå¿ èŠã§ãã&CStrãã&[u8]: ãã€ãã¹ã©ã€ã¹ã¯ãäœããã®æªç¥ã®ããŒã¿ãã«å¯Ÿããæ±çšçãªã€ã³ã¿ãŒãã§ãŒã¹ã§ãã&[u8]ãã&OsStr:&OsStrã¯OsStringãžã®éäžæ®µéã§ãããããäœæããã«ã¯OsStrExtã䜿ã£ãŠãã ããã&OsStrããOsString:&OsStrå ã®ããŒã¿ãè€è£œããŠããããè¿ããããã«ããããã«readdirãå床åŒã³åºããããã«ããå¿ èŠããããŸãã
Nomicon ã«ããFFI ã«é¢ããéåžžã«æçšãªç« ããããŸãã
以äžã®ã³ãŒãã https://play.rust-lang.org/ ã«ã³ããŒããäžè¶³ããŠãã颿°ãšã¡ãœãããåããŠãã ããã
// Copyright 2023 Google LLC // SPDX-License-Identifier: Apache-2.0 // TODO: å®è£ ãå®äºããããããåé€ããŠãã ããã #![allow(unused_imports, unused_variables, dead_code)] mod ffi { use std::os::raw::{c_char, c_int}; #[cfg(not(target_os = "macos"))] use std::os::raw::{c_long, c_uchar, c_ulong, c_ushort}; // Opaque type. See https://doc.rust-lang.org/nomicon/ffi.html. #[repr(C)] pub struct DIR { _data: [u8; 0], _marker: core::marker::PhantomData<(*mut u8, core::marker::PhantomPinned)>, } // Layout according to the Linux man page for readdir(3), where ino_t and // off_t are resolved according to the definitions in // /usr/include/x86_64-linux-gnu/{sys/types.h, bits/typesizes.h}. #[cfg(not(target_os = "macos"))] #[repr(C)] pub struct dirent { pub d_ino: c_ulong, pub d_off: c_long, pub d_reclen: c_ushort, pub d_type: c_uchar, pub d_name: [c_char; 256], } // Layout according to the macOS man page for dir(5). #[cfg(target_os = "macos")] #[repr(C)] pub struct dirent { pub d_fileno: u64, pub d_seekoff: u64, pub d_reclen: u16, pub d_namlen: u16, pub d_type: u8, pub d_name: [c_char; 1024], } unsafe extern "C" { pub unsafe fn opendir(s: *const c_char) -> *mut DIR; #[cfg(not(all(target_os = "macos", target_arch = "x86_64")))] pub unsafe fn readdir(s: *mut DIR) -> *const dirent; // See https://github.com/rust-lang/libc/issues/414 and the section on // _DARWIN_FEATURE_64_BIT_INODE in the macOS man page for stat(2). // // "Platforms that existed before these updates were available" refers // to macOS (as opposed to iOS / wearOS / etc.) on Intel and PowerPC. #[cfg(all(target_os = "macos", target_arch = "x86_64"))] #[link_name = "readdir$INODE64"] pub unsafe fn readdir(s: *mut DIR) -> *const dirent; pub unsafe fn closedir(s: *mut DIR) -> c_int; } } use std::ffi::{CStr, CString, OsStr, OsString}; use std::os::unix::ffi::OsStrExt; #[derive(Debug)] struct DirectoryIterator { path: CString, dir: *mut ffi::DIR, } impl DirectoryIterator { fn new(path: &str) -> Result<DirectoryIterator, String> { // Call opendir and return a Ok value if that worked, // otherwise return Err with a message. todo!() } } impl Iterator for DirectoryIterator { type Item = OsString; fn next(&mut self) -> Option<OsString> { // Keep calling readdir until we get a NULL pointer back. todo!() } } impl Drop for DirectoryIterator { fn drop(&mut self) { // Call closedir as needed. todo!() } } fn main() -> Result<(), String> { let iter = DirectoryIterator::new(".")?; println!("files: {:#?}", iter.collect::<Vec<_>>()); Ok(()) }
FFI ãã€ã³ãã£ã³ã°ã®ã³ãŒãã¯ãéåžžãããã§è¡ã£ãŠããããã«æäœæ¥ã§æžãã®ã§ã¯ãªããbindgen ã®ãããªããŒã«ã«ãã£ãŠçæãããŸãããã ããbindgen ã¯ãªã³ã©ã€ã³ã® playground ã§ã¯å®è¡ã§ããŸããã
è§£ç
// Copyright 2023 Google LLC // SPDX-License-Identifier: Apache-2.0 mod ffi { use std::os::raw::{c_char, c_int}; #[cfg(not(target_os = "macos"))] use std::os::raw::{c_long, c_uchar, c_ulong, c_ushort}; // Opaque type. See https://doc.rust-lang.org/nomicon/ffi.html. #[repr(C)] pub struct DIR { _data: [u8; 0], _marker: core::marker::PhantomData<(*mut u8, core::marker::PhantomPinned)>, } // Layout according to the Linux man page for readdir(3), where ino_t and // off_t are resolved according to the definitions in // /usr/include/x86_64-linux-gnu/{sys/types.h, bits/typesizes.h}. #[cfg(not(target_os = "macos"))] #[repr(C)] pub struct dirent { pub d_ino: c_ulong, pub d_off: c_long, pub d_reclen: c_ushort, pub d_type: c_uchar, pub d_name: [c_char; 256], } // Layout according to the macOS man page for dir(5). #[cfg(target_os = "macos")] #[repr(C)] pub struct dirent { pub d_fileno: u64, pub d_seekoff: u64, pub d_reclen: u16, pub d_namlen: u16, pub d_type: u8, pub d_name: [c_char; 1024], } unsafe extern "C" { pub unsafe fn opendir(s: *const c_char) -> *mut DIR; #[cfg(not(all(target_os = "macos", target_arch = "x86_64")))] pub unsafe fn readdir(s: *mut DIR) -> *const dirent; // See https://github.com/rust-lang/libc/issues/414 and the section on // _DARWIN_FEATURE_64_BIT_INODE in the macOS man page for stat(2). // // "Platforms that existed before these updates were available" refers // to macOS (as opposed to iOS / wearOS / etc.) on Intel and PowerPC. #[cfg(all(target_os = "macos", target_arch = "x86_64"))] #[link_name = "readdir$INODE64"] pub unsafe fn readdir(s: *mut DIR) -> *const dirent; pub unsafe fn closedir(s: *mut DIR) -> c_int; } } use std::ffi::{CStr, CString, OsStr, OsString}; use std::os::unix::ffi::OsStrExt; #[derive(Debug)] struct DirectoryIterator { path: CString, dir: *mut ffi::DIR, } impl DirectoryIterator { fn new(path: &str) -> Result<DirectoryIterator, String> { // Call opendir and return a Ok value if that worked, // otherwise return Err with a message. let path = CString::new(path).map_err(|err| format!("Invalid path: {err}"))?; // SAFETY: path.as_ptr() cannot be NULL. let dir = unsafe { ffi::opendir(path.as_ptr()) }; if dir.is_null() { Err(format!("Could not open {path:?}")) } else { Ok(DirectoryIterator { path, dir }) } } } impl Iterator for DirectoryIterator { type Item = OsString; fn next(&mut self) -> Option<OsString> { // Keep calling readdir until we get a NULL pointer back. // SAFETY: self.dir is never NULL. let dirent = unsafe { ffi::readdir(self.dir) }; if dirent.is_null() { // We have reached the end of the directory. return None; } // SAFETY: dirent is not NULL and dirent.d_name is NUL // terminated. let d_name = unsafe { CStr::from_ptr((*dirent).d_name.as_ptr()) }; let os_str = OsStr::from_bytes(d_name.to_bytes()); Some(os_str.to_owned()) } } impl Drop for DirectoryIterator { fn drop(&mut self) { // Call closedir as needed. // SAFETY: self.dir is never NULL. if unsafe { ffi::closedir(self.dir) } != 0 { panic!("Could not close {:?}", self.path); } } } fn main() -> Result<(), String> { let iter = DirectoryIterator::new(".")?; println!("files: {:#?}", iter.collect::<Vec<_>>()); Ok(()) } #[cfg(test)] mod tests { use super::*; use std::error::Error; #[test] fn test_nonexisting_directory() { let iter = DirectoryIterator::new("no-such-directory"); assert!(iter.is_err()); } #[test] fn test_empty_directory() -> Result<(), Box<dyn Error>> { let tmp = tempfile::TempDir::new()?; let iter = DirectoryIterator::new( tmp.path().to_str().ok_or("Non UTF-8 character in path")?, )?; let mut entries = iter.collect::<Vec<_>>(); entries.sort(); assert_eq!(entries, &[".", ".."]); Ok(()) } #[test] fn test_nonempty_directory() -> Result<(), Box<dyn Error>> { let tmp = tempfile::TempDir::new()?; std::fs::write(tmp.path().join("foo.txt"), "The Foo Diaries\n")?; std::fs::write(tmp.path().join("bar.png"), "<PNG>\n")?; std::fs::write(tmp.path().join("crab.rs"), "//! Crab\n")?; let iter = DirectoryIterator::new( tmp.path().to_str().ok_or("Non UTF-8 character in path")?, )?; let mut entries = iter.collect::<Vec<_>>(); entries.sort(); assert_eq!(entries, &[".", "..", "bar.png", "crab.rs", "foo.txt"]); Ok(()) } }
- å®å
šæ§ã³ã¡ã³ã: å
unsafeãããã¯ã®åã«ã¯ããã®æäœããªãå®å šãªã®ãã説æãã// SAFETY:ã³ã¡ã³ãã眮ãããŠããŸããããã¯ç£æ»ã容æã«ããããã®ãRust ã«ãããæšæºçãªæ £è¡ã§ãã - æåå倿: ãã®ã³ãŒãã¯ãFFI ã«å¿
èŠãªå€æã瀺ããŠããŸã:
&str->CString: C çšã®ãã«çµç«¯æååãäœæãããããCString->*const c_char: ãã€ã³ã¿ã C ã«æž¡ãããã*const c_char->&CStr: è¿ããã C æååãã©ããããããã&CStr->&[u8]->&OsStr->OsString: ãã€ãåã Rust ã® OS æååã«æ»ãããã
- RAII (
Drop): ã€ãã¬ãŒã¿ãã¹ã³ãŒããå€ãããšãã«closedirãèªåçã«åŒã³åºãããã«Dropãå®è£ ããŠããŸããããã«ããããã¡ã€ã«ãã£ã¹ã¯ãªãã¿ã®ãªãŒã¯ãé²ããŸãã - ã€ãã¬ãŒã¿ã€ã³ã¿ãŒãã§ãŒã¹: C API ã Rust ã®
Iteratorã§ã©ããããåºç€ãšãªã unsafe 㪠C 颿°ã«å¯ŸããŠãå®å šã§ Rust ãããã€ã³ã¿ãŒãã§ãŒã¹ïŒnextã¯Option<OsString>ãè¿ãïŒãæäŸããŸãã
CStringã¯ïŒStringã®ããã«ïŒããŒã¿ãææããŸãããCStr㯠ïŒ&strã®ãããªïŒåçšåç §ã§ãã- ãã€ãåãçŽæ¥
OsStrã«å€æããã«ã¯ãUnix ã·ã¹ãã ã§ã¯OsStrExtãã¬ã€ããå¿ èŠã§ãã
Android ã«ããã Rust ãžãããã
Rust 㯠Android ã®ã·ã¹ãã ãœãããŠã§ã¢ã§ãµããŒããããŠããŸããããã¯ã æ°ãããµãŒãã¹ãã©ã€ãã©ãªããã©ã€ããŒãããã«ã¯ãã¡ãŒã ãŠã§ã¢ãŸã§ã Rust ã§èšè¿°ãããã å¿ èŠã«å¿ããŠæ¢åã®ã³ãŒããæ¹åãããã§ããããšãæå³ããŸãã
Android ã§ Rust ã®å©çšãå¢ããŠããããšãèžãŸãããšãè¬æŒè ã¯æ¬¡ã® ããããã«èšåããå ŽåããããŸã:
-
ãµãŒãã¹ã®äŸ: DNS over HTTP.
-
ã©ã€ãã©ãª: Rutabaga Virtual Graphics Interface.
-
ã«ãŒãã«ãã©ã€ããŒ: Binder.
-
ãã¡ãŒã ãŠã§ã¢: pKVM firmware.
ã»ããã¢ãã
ã³ãŒãããã¹ãããããã«ãCuttlefish Android Virtual Device ã䜿çšããŸããã¢ã¯ã»ã¹ã§ãããã®ãããããšã確èªããããæ¬¡ã®ã³ãã³ãã§æ°ããäœæããŠãã ããã
source build/envsetup.sh
lunch aosp_cf_x86_64_phone-trunk_staging-userdebug
acloud create
詳现ã«ã€ããŠã¯ã Android Developer Codelab ã åç §ããŠãã ããã
以éã®ããŒãžã«ããã³ãŒãã¯ãã³ãŒã¹ææã® src/android/ ãã£ã¬ã¯ã㪠ã«ãããŸããå
å®¹ã«æ²¿ã£ãŠé²ããã«ã¯ããªããžããªã git clone ããŠãã ããã
éèŠãªãã€ã³ã:
-
Cuttlefish ã¯ãæ±çš Linux ãã¹ã¯ãããäžã§åäœããããã«èšèšããã ãªãã¡ã¬ã³ã¹ Android ããã€ã¹ã§ããMacOS ã®ãµããŒããèšç»ãããŠããŸãã
-
Cuttlefish ã·ã¹ãã ã€ã¡ãŒãžã¯å®æ©ã«å¯ŸããŠé«ãå¿ å®åºŠãç¶æããŠãããå€ãã® Rust ã®ãŠãŒã¹ã±ãŒã¹ãå®è¡ããã®ã«çæ³çãªãšãã¥ã¬ãŒã¿ã§ãã
ãã«ãã«ãŒã«
Android ãã«ãã·ã¹ãã ïŒSoongïŒã¯ãããã€ãã®ã¢ãžã¥ãŒã«ãéã㊠Rust ããµããŒãããŠããŸãã
| ã¢ãžã¥ãŒã« ã¿ã€ã | 説æ |
|---|---|
rust_binary | Rust ãã€ããªãçæããŸãã |
rust_library | Rust ã©ã€ãã©ãªãçæããrlib ãš dylib ã®äž¡æ¹ã®ããªã¢ã³ããæäŸããŸãã |
rust_ffi | cc ã¢ãžã¥ãŒã«ã§å©çšå¯èœãª Rust C ã©ã€ãã©ãªãçæããéççãšå
±æçã®äž¡æ¹ã®ããªã¢ã³ããæäŸããŸãã |
rust_proc_macro | proc-macro Rust ã©ã€ãã©ãªãçæããŸãããããã¯ã³ã³ãã€ã©ãã©ã°ã€ã³ã«çžåœããŸãã |
rust_test | æšæºã® Rust ãã¹ãããŒãã¹ã䜿çšãã Rust ãã¹ããã€ããªãçæããŸãã |
rust_fuzz | libfuzzer ãæŽ»çšãã Rust ãã¡ãºãã€ããªãçæããŸãã |
rust_protobuf | ãœãŒã¹ãçæããç¹å®ã® protobuf ã«å¯Ÿããã€ã³ã¿ãŒãã§ãŒã¹ãæäŸãã Rust ã©ã€ãã©ãªãçæããŸãã |
rust_bindgen | ãœãŒã¹ãçæããC ã©ã€ãã©ãªãžã® Rust ãã€ã³ãã£ã³ã°ãå«ã Rust ã©ã€ãã©ãªãçæããŸãã |
次ã«ãrust_binary ãš rust_library ãèŠãŠãããŸãã
çºè¡šè ãè§Šããå¯èœæ§ã®ãã远å é ç®:
-
Cargo ã¯å€èšèªãªããžããªåãã«æé©åãããŠããããããã«ã€ã³ã¿ãŒããããã ããã±ãŒãžãããŠã³ããŒãããŸãã
-
ã³ã³ãã©ã€ã¢ã³ã¹ãšããã©ãŒãã³ã¹ã®ãããAndroid ã§ã¯ã¯ã¬ãŒããããªãŒå ã« æã€å¿ èŠããããŸãããŸããC/C++/Java ã³ãŒããšçžäºéçšã§ããå¿ èŠããããŸãã Soong ã¯ãã®ã®ã£ãããåããŸãã
-
Soong ã«ã¯ Bazel ãšã®å€ãã®é¡äŒŒç¹ããããŸããBazel 㯠BlazeïŒgoogle3 ã§äœ¿çšãããŠããïŒã®ãªãŒãã³ãœãŒã¹çã§ãã
-
è±ç¥è: Star Trek ã® Data 㯠Soong å Android ã§ãã
Rust ãã€ããª
ã·ã³ãã«ãªã¢ããªã±ãŒã·ã§ã³ããå§ããŸããããAOSP ãã§ãã¯ã¢ãŠãã®ã«ãŒãã§ã次ã®ãã¡ã€ã«ãäœæããŸã:
hello_rust/Android.bp:
rust_binary {
name: "hello_rust",
crate_name: "hello_rust",
srcs: ["src/main.rs"],
}
hello_rust/src/main.rs:
// Copyright 2022 Google LLC // SPDX-License-Identifier: Apache-2.0 //! Rust demo. /// Prints a greeting to standard output. fn main() { println!("Hello from Rust!"); }
ããã§ãã€ããªããã«ãããããã·ã¥ããŠãå®è¡ã§ããŸã:
m hello_rust
adb push "$ANDROID_PRODUCT_OUT/system/bin/hello_rust" /data/local/tmp
adb shell /data/local/tmp/hello_rust
Hello from Rust!
-
ãã«ãæé ãé ã«å®è¡ãããšãã¥ã¬ãŒã¿äžã§åäœããããšã瀺ããŠãã ããã
-
å å®ããããã¥ã¡ã³ãã³ã¡ã³ãã«æ³šç®ããŠãã ãããAndroid ã®ãã«ãã«ãŒã«ã§ã¯ããã¹ãŠã®ã¢ãžã¥ãŒã«ã«ããã¥ã¡ã³ããããããšã匷å¶ãããŸãããããåé€ããŠãã©ã®ãããªãšã©ãŒãåºãã確èªããŠã¿ãŠãã ããã
-
Rust ã®ãã«ãã«ãŒã«ãä»ã® Soong ã«ãŒã«ãšåãããã«èŠããããšã匷調ããŠãã ãããããã¯ãRust ã C++ ã Java ãšåããããç°¡åã«äœ¿ããããã«ããããã®èšèšã§ãã
Rust ã©ã€ãã©ãª
Android åãã®æ°ãã Rust ã©ã€ãã©ãªãäœæããã«ã¯ãrust_library ã䜿çšããŸãã
ããã§ã¯ã2 ã€ã®ã©ã€ãã©ãªãžã®äŸåé¢ä¿ã宣èšããŸãã
libgreetingãããã¯ä»¥äžã§å®çŸ©ããŸããlibtextwrapãããã¯ããã§ã«external/rust/android-crates-io/crates/ã« vendored æžã¿ã® crate ã§ãã
hello_rust/Android.bp:
rust_binary {
name: "hello_rust_with_dep",
crate_name: "hello_rust_with_dep",
srcs: ["src/main.rs"],
rustlibs: [
"libgreetings",
"libtextwrap",
],
prefer_rlib: true, // Need this to avoid dynamic link error.
}
rust_library {
name: "libgreetings",
crate_name: "greetings",
srcs: ["src/lib.rs"],
}
hello_rust/src/main.rs:
// Copyright 2022 Google LLC
// SPDX-License-Identifier: Apache-2.0
//! Rust demo.
use greetings::greeting;
use textwrap::fill;
/// Prints a greeting to standard output.
fn main() {
println!("{}", fill(&greeting("Bob"), 24));
}
hello_rust/src/lib.rs:
// Copyright 2022 Google LLC
// SPDX-License-Identifier: Apache-2.0
//! Greeting library.
/// Greet `name`.
pub fn greeting(name: &str) -> String {
format!("Hello {name}, it is very nice to meet you!")
}
å ã»ã©ãšåãããã«ããã€ããªããã«ããããã·ã¥ããŠå®è¡ããŸãã
m hello_rust_with_dep
adb push "$ANDROID_PRODUCT_OUT/system/bin/hello_rust_with_dep" /data/local/tmp
adb shell /data/local/tmp/hello_rust_with_dep
Hello Bob, it is very
nice to meet you!
-
ãã«ãæé ãäžéãå®è¡ãããããããšãã¥ã¬ãŒã¿äžã§åäœããããšã瀺ããŠãã ããã
-
greetingsãšããååã® Rust crate ã¯ãlibgreetingsãšããã«ãŒã«ã§ãã«ãããå¿ èŠããããŸãã Rust ã³ãŒããéåžžã® Rust ãšåæ§ã« crate åã䜿ã£ãŠããããšã«æ³šæããŠãã ããã -
ç¹°ãè¿ãã«ãªããŸããããã«ãã«ãŒã«ã«ãã£ãŠããã¹ãŠã® public ãªé ç®ã«ããã¥ã¡ã³ãã³ã¡ã³ãã远å ããããšã匷å¶ãããŸãã
AIDLïŒAndroidã€ã³ã¿ãŒãã§ã€ã¹å®çŸ©èšèªïŒ
Rust ã¯ãAndroid Interface Definition LanguageïŒAIDLïŒ ããµããŒãããŠããŸãã
- Rust ã³ãŒãããæ¢åã® AIDL ãµãŒããŒãåŒã³åºãããšãã§ããŸãã
- Rust ã§æ°ãã AIDL ãµãŒããŒãäœæã§ããŸãã
-
AIDL ã䜿çšãããšãAndroid ã¢ããªå士ãçžäºã«ããåãã§ããŸãã
-
Rust ã¯ãã®ãšã³ã·ã¹ãã ã«ããã第äžçŽã®ååšã§ãããããããã€ã¹äžã®ä»ã®ããã»ã¹ãã Rust ãµãŒãã¹ãåŒã³åºãããšãã§ããŸãã
Birthday Service ãã¥ãŒããªã¢ã«
Binder ã§ Rust ã䜿çšããæ¹æ³ã説æããããã«ãBinder ã€ã³ã¿ãŒãã§ãŒã¹ãäœæããŸããæ¬¡ã«ããµãŒãã¹ãå®è£ ãããããšéä¿¡ããã¯ã©ã€ã¢ã³ããäœæããŸãã
AIDL ã€ã³ã¿ãŒãã§ãŒã¹
AIDL ã€ã³ã¿ãŒãã§ãŒã¹ã䜿çšããŠããµãŒãã¹ã® API ã宣èšããŸãã
birthday_service/aidl/com/example/birthdayservice/IBirthdayService.aidl:
package com.example.birthdayservice;
/** Birthday service interface. */
interface IBirthdayService {
/** Generate a Happy Birthday message. */
String wishHappyBirthday(String name, int years);
}
birthday_service/aidl/Android.bp:
aidl_interface {
name: "com.example.birthdayservice",
srcs: ["com/example/birthdayservice/*.aidl"],
unstable: true,
backend: {
rust: { // Rust is not enabled by default
enabled: true,
},
},
}
aidl/ãã£ã¬ã¯ããªé äžã®ãã£ã¬ã¯ããªæ§é ã¯ãAIDL ãã¡ã€ã«ã§äœ¿çšããã ããã±ãŒãžåãšäžèŽããŠããå¿ èŠãããããšã«æ³šæããŠãã ãããã€ãŸããããã±ãŒãžã¯com.example.birthdayserviceã§ããã¡ã€ã«ã¯aidl/com/example/IBirthdayService.aidlã«ãããŸãã
çæããããµãŒãã¹ API
Binder ã¯ãåã€ã³ã¿ãŒãã§ãŒã¹å®çŸ©ã«å¯ŸããŠãã¬ã€ããçæããŸãã
birthday_service/aidl/com/example/birthdayservice/IBirthdayService.aidl:
/** Birthday service interface. */
interface IBirthdayService {
/** Generate a Happy Birthday message. */
String wishHappyBirthday(String name, int years);
}
out/soong/.intermediates/âŠ/com_example_birthdayservice.rs:
// Copyright 2024 Google LLC
// SPDX-License-Identifier: Apache-2.0
trait IBirthdayService {
fn wishHappyBirthday(&self, name: &str, years: i32) -> binder::Result<String>;
}
ãµãŒãã¹ã¯ãã®ãã¬ã€ããå®è£ ããå¿ èŠããããã¯ã©ã€ã¢ã³ãã¯ãã® ãã¬ã€ãã䜿çšããŠãµãŒãã¹ãšããåãããŸãã
- çæããã颿°ã·ã°ããã£ãç¹ã«åŒæ°ãšè¿ãå€ã®åããã€ã³ã¿ãŒãã§ãŒã¹å®çŸ©ã« ã©ã®ããã«å¯Ÿå¿ããŠããããææããŠãã ããã
- åŒæ°ã®
Stringã¯ãè¿ãå€ã®Stringãšã¯ç°ãªã Rust ã®åã« ãªããŸãã
- åŒæ°ã®
ãµãŒãã¹ã®å®è£
ããã§ AIDL ãµãŒãã¹ãå®è£ ã§ããŸãã
birthday_service/src/lib.rs:
// Copyright 2024 Google LLC
// SPDX-License-Identifier: Apache-2.0
//! `IBirthdayService` AIDL ã€ã³ã¿ãŒãã§ãŒã¹ã®å®è£
ã
use com_example_birthdayservice::aidl::com::example::birthdayservice::IBirthdayService::IBirthdayService;
use com_example_birthdayservice::binder;
/// The `IBirthdayService` implementation.
pub struct BirthdayService;
impl binder::Interface for BirthdayService {}
impl IBirthdayService for BirthdayService {
fn wishHappyBirthday(&self, name: &str, years: i32) -> binder::Result<String> {
Ok(format!("Happy Birthday {name}, congratulations with the {years} years!"))
}
}
birthday_service/Android.bp:
rust_library {
name: "libbirthdayservice",
crate_name: "birthdayservice",
srcs: ["src/lib.rs"],
rustlibs: [
"com.example.birthdayservice-rust",
],
}
- çæããã
IBirthdayServiceãã¬ã€ããžã®ãã¹ã瀺ããåã»ã°ã¡ã³ããããããå¿ èŠã§ããçç±ã説æããŠãã ããã wishHappyBirthdayãšãã®ä»ã® AIDL IPC ã¡ãœããã¯ã&mut selfã§ã¯ãªã&selfãåãåãç¹ã«æ³šæããŠãã ããã- ããã¯ãBinder ãåä¿¡ãããªã¯ãšã¹ãã«ã¹ã¬ããããŒã«äžã§å¿çããè€æ°ã®ãªã¯ãšã¹ãã䞊åã«åŠçã§ããããã«ããããã«å¿
èŠã§ããããã«ããããµãŒãã¹ã¡ãœããã¯
selfãžã®å ±æåç §ããåãåããŸããã - ãµãŒãã¹ã«ãã£ãŠå€æŽããå¿
èŠãããç¶æ
ã¯ãå®å
šã«å€æŽã§ããããã«
Mutexã®ãããªãã®ã«å ¥ããå¿ èŠããããŸãã - ãµãŒãã¹ç¶æ ã管çããé©åãªæ¹æ³ã¯ããµãŒãã¹ã®è©³çްã«å€§ããäŸåããŸãã
- ããã¯ãBinder ãåä¿¡ãããªã¯ãšã¹ãã«ã¹ã¬ããããŒã«äžã§å¿çããè€æ°ã®ãªã¯ãšã¹ãã䞊åã«åŠçã§ããããã«ããããã«å¿
èŠã§ããããã«ããããµãŒãã¹ã¡ãœããã¯
- TODO:
binder::Interfaceãã¬ã€ãã¯äœãããã®ã§ããããããªãŒããŒã©ã€ãããã¡ãœããã¯ãããŸããããœãŒã¹ã¯ã©ãã«ãããŸããã
AIDL ãµãŒããŒ
æåŸã«ããµãŒãã¹ãå ¬éãããµãŒããŒãäœæã§ããŸãã
birthday_service/src/server.rs:
// Copyright 2024 Google LLC
// SPDX-License-Identifier: Apache-2.0
//! Birthday service.
use birthdayservice::BirthdayService;
use com_example_birthdayservice::aidl::com::example::birthdayservice::IBirthdayService::BnBirthdayService;
use com_example_birthdayservice::binder;
const SERVICE_IDENTIFIER: &str = "birthdayservice";
/// Entry point for birthday service.
fn main() {
let birthday_service = BirthdayService;
let birthday_service_binder = BnBirthdayService::new_binder(
birthday_service,
binder::BinderFeatures::default(),
);
binder::add_service(SERVICE_IDENTIFIER, birthday_service_binder.as_binder())
.expect("Failed to register service");
binder::ProcessState::join_thread_pool();
}
birthday_service/Android.bp:
rust_binary {
name: "birthday_server",
crate_name: "birthday_server",
srcs: ["src/server.rs"],
rustlibs: [
"com.example.birthdayservice-rust",
"libbirthdayservice",
],
prefer_rlib: true, // To avoid dynamic link error.
}
ãŠãŒã¶ãŒå®çŸ©ã®ãµãŒãã¹å®è£
ïŒãã®å Žå㯠IBirthdayService ãå®è£
ãã BirthdayService åïŒãåãåããããã Binder ãµãŒãã¹ãšããŠèµ·åãã ããã»ã¹ã«ã¯è€æ°ã®æé ããããŸããããã¯ãC++ ãä»ã®èšèªãã Binder ã 䜿ã£ãããšãããåè¬è
ã«ãšã£ãŠã¯ãæ
£ããŠãããã®ããè€éã«èŠãããããããŸããã åæé ããªãå¿
èŠãªã®ããåè¬è
ã«èª¬æããŠãã ããã
- ãµãŒãã¹åïŒ
BirthdayServiceïŒã®ã€ã³ã¹ã¿ã³ã¹ãäœæããŸãã - ãµãŒãã¹ãªããžã§ã¯ããã察å¿ãã
Bn*åïŒãã®å Žåã¯BnBirthdayServiceïŒ ã§ã©ããããŸãããã®å㯠Binder ã«ãã£ãŠçæãããC++ ã®BnBinderåºåºã¯ã©ã¹ã«äŒŒãå ±éã® Binder æ©èœãæäŸããŸããRust ã«ã¯ç¶æ¿ããªãããã çæãããBnBinderServiceã®äžã«BirthdayServiceãå ¥ãããšãã ã³ã³ããžã·ã§ã³ã䜿ããŸãã add_serviceãåŒã³åºãããµãŒãã¹èå¥åãšãµãŒãã¹ãªããžã§ã¯ã ïŒãã®äŸã§ã¯BnBirthdayServiceãªããžã§ã¯ãïŒãæž¡ããŸããjoin_thread_poolãåŒã³åºããŠçŸåšã®ã¹ã¬ããã Binder ã®ã¹ã¬ããããŒã«ã«è¿œå ãã æ¥ç¶ã®åŸ æ©ãéå§ããŸãã
ãããã€
ããã§ããµãŒãã¹ããã«ãããããã·ã¥ããŠèµ·åã§ããŸã:
m birthday_server
adb push "$ANDROID_PRODUCT_OUT/system/bin/birthday_server" /data/local/tmp
adb root
adb shell /data/local/tmp/birthday_server
å¥ã®ã¿ãŒããã«ã§ããµãŒãã¹ãå®è¡ãããŠããããšã確èªããŸã:
adb shell service check birthdayservice
Service birthdayservice: found
service call ã䜿ã£ãŠãµãŒãã¹ãåŒã³åºãããšãã§ããŸã:
adb shell service call birthdayservice 1 s16 Bob i32 24
Result: Parcel(
0x00000000: 00000000 00000036 00610048 00700070 '....6...H.a.p.p.'
0x00000010: 00200079 00690042 00740072 00640068 'y. .B.i.r.t.h.d.'
0x00000020: 00790061 00420020 0062006f 0020002c 'a.y. .B.o.b.,. .'
0x00000030: 006f0063 0067006e 00610072 00750074 'c.o.n.g.r.a.t.u.'
0x00000040: 0061006c 00690074 006e006f 00200073 'l.a.t.i.o.n.s. .'
0x00000050: 00690077 00680074 00740020 00650068 'w.i.t.h. .t.h.e.'
0x00000060: 00320020 00200034 00650079 00720061 ' .2.4. .y.e.a.r.'
0x00000070: 00210073 00000000 's.!..... ')
AIDL ã¯ã©ã€ã¢ã³ã
æåŸã«ãæ°ãããµãŒãã¹çšã® Rust ã¯ã©ã€ã¢ã³ããäœæã§ããŸãã
birthday_service/src/client.rs:
// Copyright 2024 Google LLC
// SPDX-License-Identifier: Apache-2.0
use com_example_birthdayservice::aidl::com::example::birthdayservice::IBirthdayService::IBirthdayService;
use com_example_birthdayservice::binder;
const SERVICE_IDENTIFIER: &str = "birthdayservice";
/// Call the birthday service.
fn main() -> Result<(), Box<dyn Error>> {
let name = std::env::args().nth(1).unwrap_or_else(|| String::from("Bob"));
let years = std::env::args()
.nth(2)
.and_then(|arg| arg.parse::<i32>().ok())
.unwrap_or(42);
binder::ProcessState::start_thread_pool();
let service = binder::get_interface::<dyn IBirthdayService>(SERVICE_IDENTIFIER)
.map_err(|_| "Failed to connect to BirthdayService")?;
// Call the service.
let msg = service.wishHappyBirthday(&name, years)?;
println!("{msg}");
}
birthday_service/Android.bp:
rust_binary {
name: "birthday_client",
crate_name: "birthday_client",
srcs: ["src/client.rs"],
rustlibs: [
"com.example.birthdayservice-rust",
],
prefer_rlib: true, // To avoid dynamic link error.
}
ã¯ã©ã€ã¢ã³ã㯠libbirthdayservice ã«äŸåããªãããšã«æ³šæããŠãã ããã
ã¯ã©ã€ã¢ã³ãããã«ãããããã€ã¹ã«ããã·ã¥ããŠå®è¡ããŸãã
m birthday_client
adb push "$ANDROID_PRODUCT_OUT/system/bin/birthday_client" /data/local/tmp
adb shell /data/local/tmp/birthday_client Charlie 60
Happy Birthday Charlie, congratulations with the 60 years!
Strong<dyn IBirthdayService>ã¯ãã¯ã©ã€ã¢ã³ããæ¥ç¶ãããµãŒãã¹ã衚ããã¬ã€ããªããžã§ã¯ãã§ããStrong㯠Binder çšã®ã«ã¹ã¿ã ã¹ããŒããã€ã³ã¿åã§ããããã¯ããµãŒãã¹ã®ãã¬ã€ããªããžã§ã¯ãã«å¯Ÿããããã»ã¹å ã®åç §ã«ãŠã³ããšããã®ãªããžã§ã¯ããåç §ããŠããããã»ã¹æ°ã远跡ããã°ããŒãã«ãª Binder ã®åç §ã«ãŠã³ãã®äž¡æ¹ãåŠçããŸãã- ã¯ã©ã€ã¢ã³ãããµãŒãã¹ãšããåãããããã«äœ¿çšãããã¬ã€ããªããžã§ã¯ãã¯ããµãŒããŒãå®è£ ãããã®ãšãŸã£ããåããã¬ã€ãã䜿çšããããšã«æ³šæããŠãã ãããç¹å®ã® Binder ã€ã³ã¿ãŒãã§ãŒã¹ã«å¯ŸããŠçæããã Rust ã®ãã¬ã€ã㯠1 ã€ã ãã§ãããã¯ã©ã€ã¢ã³ããšãµãŒããŒã®äž¡æ¹ãããã䜿çšããŸãã
- ãµãŒãã¹ã®ç»é²æã«äœ¿çšãããã®ãšåããµãŒãã¹èå¥åã䜿çšããŸããçæ³çã«ã¯ãããã¯ã¯ã©ã€ã¢ã³ããšãµãŒããŒã®äž¡æ¹ãäŸåã§ããå ±éã®ã¯ã¬ãŒãã§å®çŸ©ããã®ãããã§ãããã
API ã®å€æŽ
API ãæ¡åŒµããŸããããã¯ã©ã€ã¢ã³ããããŒã¹ããŒã«ãŒãã®è¡ã®ãªã¹ãã æå®ã§ããããã«ããŸã:
package com.example.birthdayservice;
/** ããŒã¹ããŒãµãŒãã¹ã®ã€ã³ã¿ãŒãã§ãŒã¹ã */
interface IBirthdayService {
/** Happy Birthday ã¡ãã»ãŒãžãçæããŸãã */
String wishHappyBirthday(String name, int years, in String[] text);
}
ããã«ãããIBirthdayService ã®ãã¬ã€ãå®çŸ©ã¯æ¬¡ã®ããã«æŽæ°ãããŸã:
// Copyright 2024 Google LLC
// SPDX-License-Identifier: Apache-2.0
trait IBirthdayService {
fn wishHappyBirthday(
&self,
name: &str,
years: i32,
text: &[String],
) -> binder::Result<String>;
}
- AIDL å®çŸ©ã®
String[]ã Rust ã§ã¯&[String]ã«å€æãããŠããããšã« 泚ç®ããŠãã ãããã€ãŸããçæããããã€ã³ãã£ã³ã°ã§ã¯å¯èœãªéã æ £çšç㪠Rust ã®åã䜿çšãããŸã:iné ååŒæ°ã¯ã¹ã©ã€ã¹ã«å€æãããŸããoutåŒæ°ãšinoutåŒæ°ã¯&mut Vec<T>ã«å€æãããŸãã- æ»ãå€ã¯
Vec<T>ãè¿ã圢ã«å€æãããŸãã
ã¯ã©ã€ã¢ã³ããšãµãŒãã¹ã®æŽæ°
æ°ãã API ã«å¯Ÿå¿ããããã«ãã¯ã©ã€ã¢ã³ããšãµãŒããŒã®ã³ãŒããæŽæ°ããŸãã
birthday_service/src/lib.rs:
// Copyright 2024 Google LLC
// SPDX-License-Identifier: Apache-2.0
impl IBirthdayService for BirthdayService {
fn wishHappyBirthday(
&self,
name: &str,
years: i32,
text: &[String],
) -> binder::Result<String> {
let mut msg = format!(
"Happy Birthday {name}, congratulations with the {years} years!",
);
for line in text {
msg.push('\n');
msg.push_str(line);
}
Ok(msg)
}
}
birthday_service/src/client.rs:
// Copyright 2024 Google LLC
// SPDX-License-Identifier: Apache-2.0
let msg = service.wishHappyBirthday(
&name,
years,
&[
String::from("Habby birfday to yuuuuu"),
String::from("And also: many more"),
],
)?;
- TODO: ã³ãŒãã¹ããããããå®éã«ãã«ãããããããžã§ã¯ããã¡ã€ã«å ã«ç§»åããïŒ
AIDL åã®æäœ
AIDL ã®åã¯ãé©åã§ Rust ãããåã«å€æãããŸãã
- ããªããã£ãåã¯ãïŒã»ãšãã©ã®å ŽåïŒRust ãããåã«å¯Ÿå¿ä»ããããŸãã
- ã¹ã©ã€ã¹ã
Vecãæåååãªã©ã®ã³ã¬ã¯ã·ã§ã³åããµããŒããããŠããŸãã - AIDL ãªããžã§ã¯ãããã³ãã¡ã€ã«ãã³ãã«ãžã®åç §ã¯ãã¯ã©ã€ã¢ã³ããšãµãŒãã¹ã®éã§éä¿¡ã§ããŸãã
- ãã¡ã€ã«ãã³ãã«ãš Parcelable ã¯å®å šã«ãµããŒããããŠããŸãã
ããªããã£ãå
ããªããã£ãåã¯ïŒã»ãšãã©ã®å ŽåïŒæ £çšçã«æ¬¡ã®ããã«å¯Ÿå¿ä»ããããŸãã
| AIDL å | Rust å | æ³šèš |
|---|---|---|
boolean | bool | |
byte | i8 | ãã€ãã¯ç¬Šå·ä»ãã§ããããšã«æ³šæããŠãã ããã |
char | u16 | u32 ã§ã¯ãªããu16 ã䜿çšããããšã«æ³šæããŠãã ããã |
int | i32 | |
long | i64 | |
float | f32 | |
double | f64 | |
String | String |
é åå
é
ååïŒT[]ãbyte[]ãList<T>ïŒã¯ã颿°ã·ã°ããã£ã§ã®äœ¿ç𿹿³ã«å¿ããŠãé©å㪠Rust ã®é
ååã«å€æãããŸãã
| äœçœ® | Rust å |
|---|---|
in åŒæ° | &[T] |
out/inout åŒæ° | &mut Vec<T> |
| æ»ãå€ | Vec<T> |
- Android 13 以éã§ã¯ãåºå®ãµã€ãºé
åããµããŒããããŠããŸããã€ãŸãã
T[N]ã¯[T; N]ã«ãªããŸããåºå®ãµã€ãºé åã¯è€æ°æ¬¡å ãæã€ããšãã§ããŸãïŒäŸ:int[3][4]ïŒãJava ããã¯ãšã³ãã§ã¯ãåºå®ãµã€ãºé åã¯é ååãšããŠè¡šçŸãããŸãã - parcelable ãã£ãŒã«ãå
ã®é
åã¯ãåžžã«
Vec<T>ã«å€æãããŸãã
ãªããžã§ã¯ãã®éä¿¡
AIDL ãªããžã§ã¯ãã¯ãå
·äœç㪠AIDL åãšããŠéä¿¡ããããšããåæ¶å»ããã IBinder ã€ã³ã¿ãŒãã§ãŒã¹ãšããŠéä¿¡ããããšãã§ããŸãã
birthday_service/aidl/com/example/birthdayservice/IBirthdayInfoProvider.aidl:
package com.example.birthdayservice;
interface IBirthdayInfoProvider {
String name();
int years();
}
birthday_service/aidl/com/example/birthdayservice/IBirthdayService.aidl:
import com.example.birthdayservice.IBirthdayInfoProvider;
interface IBirthdayService {
/** The same thing, but using a binder object. */
String wishWithProvider(IBirthdayInfoProvider provider);
/** The same thing, but using `IBinder`. */
String wishWithErasedProvider(IBinder provider);
}
birthday_service/src/client.rs:
// Copyright 2024 Google LLC
// SPDX-License-Identifier: Apache-2.0
/// Rust struct implementing the `IBirthdayInfoProvider` interface.
struct InfoProvider {
name: String,
age: u8,
}
impl binder::Interface for InfoProvider {}
impl IBirthdayInfoProvider for InfoProvider {
fn name(&self) -> binder::Result<String> {
Ok(self.name.clone())
}
fn years(&self) -> binder::Result<i32> {
Ok(self.age as i32)
}
}
fn main() {
binder::ProcessState::start_thread_pool();
let service = connect().expect("Failed to connect to BirthdayService");
// Create a binder object for the `IBirthdayInfoProvider` interface.
let provider = BnBirthdayInfoProvider::new_binder(
InfoProvider { name: name.clone(), age: years as u8 },
BinderFeatures::default(),
);
// Send the binder object to the service.
service.wishWithProvider(&provider)?;
// Perform the same operation but passing the provider as an `SpIBinder`.
service.wishWithErasedProvider(&provider.as_binder())?;
}
BnBirthdayInfoProviderã®äœ¿çšã«æ³šç®ããŠãã ãããããã¯ã以åèŠãBnBirthdayServiceãšåãç®çãæãããŸãã
Parcelable
Rust åã Binder ã¯ãParcelable ãçŽæ¥éä¿¡ããããšããµããŒãããŠããŸã:
birthday_service/aidl/com/example/birthdayservice/BirthdayInfo.aidl:
package com.example.birthdayservice;
parcelable BirthdayInfo {
String name;
int years;
}
birthday_service/aidl/com/example/birthdayservice/IBirthdayService.aidl:
import com.example.birthdayservice.BirthdayInfo;
interface IBirthdayService {
/** The same thing, but with a parcelable. */
String wishWithInfo(in BirthdayInfo info);
}
birthday_service/src/client.rs:
// Copyright 2024 Google LLC
// SPDX-License-Identifier: Apache-2.0
fn main() {
binder::ProcessState::start_thread_pool();
let service = connect().expect("Failed to connect to BirthdayService");
let info = BirthdayInfo { name: "Alice".into(), years: 123 };
service.wishWithInfo(&info)?;
}
ãã¡ã€ã«ã®éä¿¡
ãã¡ã€ã«ã¯ãParcelFileDescriptor åã䜿çšã㊠Binder ã¯ã©ã€ã¢ã³ã/ãµãŒããŒéã§éä¿¡ã§ããŸã:
birthday_service/aidl/com/example/birthdayservice/IBirthdayService.aidl:
interface IBirthdayService {
/** The same thing, but loads info from a file. */
String wishFromFile(in ParcelFileDescriptor infoFile);
}
birthday_service/src/client.rs:
// Copyright 2024 Google LLC
// SPDX-License-Identifier: Apache-2.0
fn main() {
binder::ProcessState::start_thread_pool();
let service = connect().expect("Failed to connect to BirthdayService");
// Open a file and put the birthday info in it.
let mut file = File::create("/data/local/tmp/birthday.info").unwrap();
writeln!(file, "{name}")?;
writeln!(file, "{years}")?;
// Create a `ParcelFileDescriptor` from the file and send it.
let file = ParcelFileDescriptor::new(file);
service.wishFromFile(&file)?;
}
birthday_service/src/lib.rs:
// Copyright 2024 Google LLC
// SPDX-License-Identifier: Apache-2.0
impl IBirthdayService for BirthdayService {
fn wishFromFile(
&self,
info_file: &ParcelFileDescriptor,
) -> binder::Result<String> {
// Convert the file descriptor to a `File`. `ParcelFileDescriptor` wraps
// an `OwnedFd`, which can be cloned and then used to create a `File`
// object.
let mut info_file = info_file
.as_ref()
.try_clone()
.map(File::from)
.expect("Invalid file handle");
let mut contents = String::new();
info_file.read_to_string(&mut contents).unwrap();
let mut lines = contents.lines();
let name = lines.next().unwrap();
let years: i32 = lines.next().unwrap().parse().unwrap();
Ok(format!("Happy Birthday {name}, congratulations with the {years} years!"))
}
}
ParcelFileDescriptorã¯OwnedFdãã©ããããŠãããããFileïŒãŸãã¯OwnedFdãã©ãããããã®ä»ã®ä»»æã®åïŒããäœæã§ããå察åŽã§æ°ããFileãã³ãã«ãäœæããããã«äœ¿çšã§ããŸãã- ä»ã®çš®é¡ã®ãã¡ã€ã«ãã£ã¹ã¯ãªãã¿ãã©ããããŠéä¿¡ã§ããŸããããšãã°ãTCPãUDPã UNIX ãœã±ããã§ãã
Android ã§ã®ãã¹ã
ãã¹ã ãèžãŸããŠãããã§ã¯ AOSP ã§ãŠããããã¹ããã©ã®ããã« åäœããããèŠãŠãããŸãããŠããããã¹ãã«ã¯ rust_test ã¢ãžã¥ãŒã«ã䜿çšããŸã:
testing/Android.bp:
rust_library {
name: "libleftpad",
crate_name: "leftpad",
srcs: ["src/lib.rs"],
}
rust_test {
name: "libleftpad_test",
crate_name: "leftpad_test",
srcs: ["src/lib.rs"],
host_supported: true,
test_suites: ["general-tests"],
}
rust_test {
name: "libgoogletest_example",
crate_name: "googletest_example",
srcs: ["googletest.rs"],
rustlibs: ["libgoogletest_rust"],
host_supported: true,
}
rust_test {
name: "libmockall_example",
crate_name: "mockall_example",
srcs: ["mockall.rs"],
rustlibs: ["libmockall"],
host_supported: true,
}
testing/src/lib.rs:
#![allow(unused)] fn main() { // Copyright 2024 Google LLC // SPDX-License-Identifier: Apache-2.0 //! Left-padding library. /// Left-pad `s` to `width`. pub fn leftpad(s: &str, width: usize) -> String { format!("{s:>width$}") } #[cfg(test)] mod tests { use super::*; #[test] fn short_string() { assert_eq!(leftpad("foo", 5), " foo"); } #[test] fn long_string() { assert_eq!(leftpad("foobar", 6), "foobar"); } } }
ããã§ã次ã®ããã«ãã¹ããå®è¡ã§ããŸã
atest --host libleftpad_test
åºåã¯æ¬¡ã®ããã«ãªããŸã:
INFO: Elapsed time: 2.666s, Critical Path: 2.40s
INFO: 3 processes: 2 internal, 1 linux-sandbox.
INFO: Build completed successfully, 3 total actions
//comprehensive-rust-android/testing:libleftpad_test_host PASSED in 2.3s
PASSED libleftpad_test.tests::long_string (0.0s)
PASSED libleftpad_test.tests::short_string (0.0s)
Test cases: finished with 2 passing and 0 failing out of 2 test cases
ã©ã€ãã©ãªã¯ã¬ãŒãã®ã«ãŒãã ããæå®ããŠããããšã«æ³šç®ããŠãã ããããã¹ã㯠ãã¹ããããã¢ãžã¥ãŒã«å ã§ååž°çã«æ€åºãããŸãã
GoogleTest
GoogleTest ã¯ã¬ãŒãã䜿ããšããããã£ãŒ ãçšããæè»ãª ãã¹ãã¢ãµãŒã·ã§ã³ãèšè¿°ã§ããŸãã
// Copyright 2024 Google LLC
// SPDX-License-Identifier: Apache-2.0
use googletest::prelude::*;
#[googletest::test]
fn test_elements_are() {
let value = vec!["foo", "bar", "baz"];
expect_that!(value, elements_are!(eq(&"foo"), lt(&"xyz"), starts_with("b")));
}
æåŸã®èŠçŽ ã "!" ã«å€æŽãããšããã¹ãã¯ãšã©ãŒç®æãç確ã«ç€ºãæ§é åããããšã©ãŒ ã¡ãã»ãŒãžãšãšãã«å€±æããŸãã
---- test_elements_are stdout ----
Value of: value
Expected: has elements:
0. is equal to "foo"
1. is less than "xyz"
2. starts with prefix "!"
Actual: ["foo", "bar", "baz"],
where element #2 is "baz", which does not start with "!"
at src/testing/googletest.rs:6:5
Error: See failure output above
-
GoogleTest 㯠Rust Playground ã®äžéšã§ã¯ãªãããããã®äŸã¯ããŒã«ã«ç°å¢ã§å®è¡ ããå¿ èŠããããŸããæ¢åã® Cargo ãããžã§ã¯ãã«ãã°ãã远å ããã«ã¯
cargo add googletestã䜿çšããŠãã ããã -
use googletest::prelude::*;è¡ã¯ã ãã䜿ããããã¯ããšå ãããã€ãã€ã³ããŒãããŸãã -
ããã¯ã»ãã®å ¥ãå£ã«ããããçµã¿èŸŒã¿ã®ãããã£ãŒã¯æ°å€ããããŸããèªç¿åœ¢åŒã® Rust ã³ãŒã¹ âRust ã¢ããªã±ãŒã·ã§ã³ã®ããã®é«åºŠãªãã¹ãâ ã®ç¬¬ 1 ç« ãèªãã§ã¿ããšããã§ãããããã®ç« ã§ã¯ã©ã€ãã©ãªã®ã¬ã€ãä»ãå ¥éã æäŸãããŠããã
googletestã®ãã¯ãããã®ãããã£ãŒããããŠå šäœçãªèšèš ææ³ã«æ £ããã®ã«åœ¹ç«ã€æŒç¿ãå«ãŸããŠããŸãã -
ç¹ã«äŸ¿å©ãªæ©èœãšããŠãè€æ°è¡æååã®äžäžèŽãå·®åãšããŠè¡šç€ºãããŸãã
// Copyright 2024 Google LLC
// SPDX-License-Identifier: Apache-2.0
#[test]
fn test_multiline_string_diff() {
let haiku = "Memory safety found,\n\
Rust's strong typing guides the way,\n\
Secure code you'll write.";
assert_that!(
haiku,
eq("Memory safety found,\n\
Rust's silly humor guides the way,\n\
Secure code you'll write.")
);
}
è²åããããå·®åã衚瀺ãããŸãïŒããã§ã¯è²ã¯è¡šç€ºããŠããŸããïŒã
Value of: haiku
Expected: is equal to "Memory safety found,\nRust's silly humor guides the way,\nSecure code you'll write."
Actual: "Memory safety found,\nRust's strong typing guides the way,\nSecure code you'll write.",
which isn't equal to "Memory safety found,\nRust's silly humor guides the way,\nSecure code you'll write."
Difference(-actual / +expected):
Memory safety found,
-Rust's strong typing guides the way,
+Rust's silly humor guides the way,
Secure code you'll write.
at src/testing/googletest.rs:17:5
- ãã®ã¯ã¬ãŒã㯠GoogleTest for C++ ã® Rust ç§»æ€çã§ãã
ã¢ãã¯
ã¢ãã¯ã«ã¯ãMockall ãšããåºã䜿ãããŠããã©ã€ãã©ãªããããŸããã³ãŒãã ãã¬ã€ãã䜿ãããã«ãªãã¡ã¯ã¿ãªã³ã°ããå¿ èŠããããŸããããããã°ããããã ãã°ããã¢ãã¯åã§ããŸãã
// èäœæš© 2024 Google LLC
// SPDX-License-Identifier: Apache-2.0
use std::time::Duration;
#[mockall::automock]
pub trait Pet {
fn is_hungry(&self, since_last_meal: Duration) -> bool;
}
#[test]
fn test_robot_dog() {
let mut mock_dog = MockPet::new();
mock_dog.expect_is_hungry().return_const(true);
assert!(mock_dog.is_hungry(Duration::from_secs(10)));
}
-
Mockall 㯠AndroidïŒAOSPïŒã§æšå¥šãããŠããã¢ãã¯ã©ã€ãã©ãªã§ããã»ãã«ã crates.io ã§å©çšå¯èœãªã¢ãã¯ã©ã€ãã©ãª ããããç¹ã« HTTP ãµãŒãã¹ã®ã¢ãã¯ã®åéã§ã¯å€ã䜿ãããŠããŸããã»ãã® ã¢ãã¯ã©ã€ãã©ãªã Mockall ãšäŒŒãä»çµã¿ã§åäœããç¹å®ã®ãã¬ã€ãã® ã¢ãã¯å®è£ ãç°¡åã«ååŸã§ããŸãã
-
ã¢ãã¯ã¯ãã è°è«ã®ãããã® ã§ããç¹ã«æ³šæããŠãã ãããã¢ãã¯ã䜿ããšã ãã¹ãããã®äŸåé¢ä¿ããå®å šã«åé¢ã§ããŸããçŽæ¥çãªçµæãšããŠããã¹ãã® å®è¡ã¯ããé«éãã€å®å®ããŸããäžæ¹ã§ãã¢ãã¯ã誀ã£ãŠèšå®ãããå®éã® äŸåé¢ä¿ãè¿ãçµæãšã¯ç°ãªãåºåãè¿ãããšããããŸãã
å¯èœã§ããã°ãå®éã®äŸåé¢ä¿ã䜿ãããšãæšå¥šããŸããããšãã°ãå€ãã® ããŒã¿ããŒã¹ã§ã¯ã€ã³ã¡ã¢ãªããã¯ãšã³ããèšå®ã§ããŸããããã«ããããã¹ãã§ æ£ããæ¯ãèããåŸããããããé«éã§ãåŸå§æ«ãèªåçã«è¡ãããŸãã
åæ§ã«ãå€ãã® Web ãã¬ãŒã ã¯ãŒã¯ã§ã¯ã
localhostäžã®ã©ã³ãã ãªããŒãã« ãã€ã³ãããã€ã³ããã»ã¹ãµãŒããŒãèµ·åã§ããŸããã³ãŒããå®éã®ç°å¢ã§ ãã¹ãããã®ã«åœ¹ç«ã€ããããã¬ãŒã ã¯ãŒã¯ãã¢ãã¯åããŠæžãŸãããããã åžžã«ãã¡ããåªå ããŠãã ããã -
Mockall 㯠Rust Playground ã«ã¯å«ãŸããŠããªãããããã®äŸã¯ããŒã«ã«ç°å¢ã§ å®è¡ããå¿ èŠããããŸãã
cargo add mockallã䜿ããšãæ¢åã® Cargo ãããžã§ã¯ãã« Mockall ããã°ãã远å ã§ããŸãã -
Mockall ã«ã¯è±å¯ãªæ©èœããããŸããç¹ã«ãæž¡ãããåŒæ°ã«äŸåããæåŸ æ¡ä»¶ã èšå®ã§ããŸããããã§ã¯ããã䜿ã£ãŠãæåŸã«é€ãäžããŠãã 3 æéåŸã«ç©ºè ¹ã« ãªãç«ãã¢ãã¯ããŸãã
// èäœæš© 2024 Google LLC
// SPDX-License-Identifier: Apache-2.0
#[test]
fn test_robot_cat() {
let mut mock_cat = MockPet::new();
mock_cat
.expect_is_hungry()
.with(mockall::predicate::gt(Duration::from_secs(3 * 3600)))
.return_const(true);
mock_cat.expect_is_hungry().return_const(false);
assert!(mock_cat.is_hungry(Duration::from_secs(5 * 3600)));
assert!(!mock_cat.is_hungry(Duration::from_secs(5)));
}
.times(n)ã䜿ããšãã¢ãã¯ã¡ãœãããåŒã³åºãããåæ°ãnåã« å¶éã§ããŸã â ãããæºããããªãå Žåãã¢ãã¯ã¯ç Žæ£æã«èªåçã« panic ããŸãã
ãã®ã³ã°
log ã¯ã¬ãŒãã䜿çšããŠãlogcatïŒããã€ã¹äžïŒãŸã㯠stdoutïŒãã¹ãäžïŒã«èªåçã«ãã°ãåºåããŠãã ããã
hello_rust_logs/Android.bp:
rust_binary {
name: "hello_rust_logs",
crate_name: "hello_rust_logs",
srcs: ["src/main.rs"],
rustlibs: [
"liblog_rust",
"liblogger",
],
host_supported: true,
}
hello_rust_logs/src/main.rs:
// Copyright 2022 Google LLC
// SPDX-License-Identifier: Apache-2.0
//! Rust logging demo.
use log::{debug, error, info};
/// Logs a greeting.
fn main() {
logger::init(
logger::Config::default()
.with_tag_on_device("rust")
.with_max_level(log::LevelFilter::Trace),
);
debug!("Starting program.");
info!("Things are going fine.");
error!("Something went wrong!");
}
ãã€ããªããã«ãããããã€ã¹ã«ããã·ã¥ããŠå®è¡ããŸã:
m hello_rust_logs
adb push "$ANDROID_PRODUCT_OUT/system/bin/hello_rust_logs" /data/local/tmp
adb shell /data/local/tmp/hello_rust_logs
ãã°ã¯ adb logcat ã«è¡šç€ºãããŸã:
adb logcat -s rust
09-08 08:38:32.454 2420 2420 D rust: hello_rust_logs: Starting program.
09-08 08:38:32.454 2420 2420 I rust: hello_rust_logs: Things are going fine.
09-08 08:38:32.454 2420 2420 E rust: hello_rust_logs: Something went wrong!
libloggerã®ãã¬ãŒå®è£ ãå¿ èŠãªã®ã¯æçµãã€ããªã ãã§ããã ã©ã€ãã©ãªãããã°ãåºåããå Žåã«å¿ èŠãªã®ã¯logãã¡ãµãŒãã¯ã¬ãŒãã ãã§ãã
çžäºéçšæ§
Rust ã¯ä»ã®èšèªãšã®çžäºéçšæ§ãåªãã圢ã§ãµããŒãããŠããŸããããã¯ã 次ã®ããšãã§ããããšãæå³ããŸãã
- ä»ã®èšèªãã Rust ã®é¢æ°ãåŒã³åºãã
- Rust ããä»ã®èšèªã§æžããã颿°ãåŒã³åºãã
ä»èšèªã®é¢æ°ãåŒã³åºããšãã¯ãå€éšé¢æ°ã€ã³ã¿ãŒãã§ãŒã¹ïŒFFI ãšãåŒã°ããŸãïŒã䜿çšããŠããŸãã
-
ãã㯠Rust ã®éèŠãªèœåã§ããã³ã³ãã€ã«ãããã³ãŒãã¯ãã³ã³ãã€ã«ããã C ãŸã㯠C++ ã®ã³ãŒããšèŠåããã€ããªããªããŸãã
-
æè¡çã«ã¯ãRust 㯠C ã³ãŒããšåã ABIïŒã¢ããªã±ãŒã·ã§ã³ãã€ããªã€ã³ã¿ãŒãã§ãŒã¹ïŒã«ã³ã³ãã€ã«ã§ãããšèšããŸãã
C ãšã®çžäºéçšæ§
Rust ã¯ãC ã®åŒã³åºãèŠçŽãæã€ãªããžã§ã¯ããã¡ã€ã«ãšã®ãªã³ã¯ãå®å šã«ãµããŒãããŠããŸãã åæ§ã«ãRust ã®é¢æ°ããšã¯ã¹ããŒãããC ããåŒã³åºãããšãã§ããŸãã
æããªãæäœæ¥ã§è¡ãããšãã§ããŸã:
// èäœæš© 2022 Google LLC // SPDX-License-Identifier: Apache-2.0 unsafe extern "C" { safe fn abs(x: i32) -> i32; } fn main() { let x = -42; let abs_x = abs(x); println!("{x}, {abs_x}"); }
ããã¯ãã§ã« Safe FFI Wrapper ã®æŒç¿ã§èŠãŸããã
ããã¯ã察象ãã©ãããã©ãŒã ãå®å šã«ææ¡ããŠããããšãåæãšããŠããŸããæ¬çªç°å¢ã§ã® 䜿çšã¯æšå¥šãããŸããã
次ã«ãããè¯ãæ¹æ³ãèŠãŠãããŸãã
-
externãããã¯ã®"C"éšå ã¯ãabsã C ã® ABIïŒã¢ããªã±ãŒã·ã§ã³ãã€ããªã€ã³ã¿ãŒãã§ãŒã¹ïŒã䜿ã£ãŠåŒã³åºããããšã Rust ã«äŒããŸãã -
safe fn absã®éšåã¯ãabsãå®å šãªé¢æ°ã§ããããšã Rust ã«äŒããŸããããã©ã«ãã§ã¯ã extern 颿°ã¯ unsafe ã§ãããabs(x)ã¯ã©ã®ãããªxã«å¯ŸããŠãæªå®çŸ©åäœã åŒãèµ·ãããªããããå®å šãšããŠå®£èšã§ããŸãã
ã·ã³ãã«ãª C ã©ã€ãã©ãª
ãŸããå°ã㪠C ã©ã€ãã©ãªãäœæããŸããã:
interoperability/bindgen/libbirthday.h:
typedef struct card {
const char* name;
int years;
} card;
void print_card(const card* card);
interoperability/bindgen/libbirthday.c:
#include <stdio.h>
#include "libbirthday.h"
void print_card(const card* card) {
printf("+--------------\n");
printf("| Happy Birthday %s!\n", card->name);
printf("| Congratulations with the %i years!\n", card->years);
printf("+--------------\n");
}
ããã Android.bp ãã¡ã€ã«ã«è¿œå ããŸã:
interoperability/bindgen/Android.bp:
cc_library {
name: "libbirthday",
srcs: ["libbirthday.c"],
}
Bindgen ã䜿ã
bindgen ããŒã«ã¯ãC ããããŒãã¡ã€ã«ãããã€ã³ãã£ã³ã°ãèªåçæã§ããŸãã
ã©ã€ãã©ãªçšã®ã©ãããŒããããŒãã¡ã€ã«ãäœæããŸãïŒãã®äŸã§ã¯å³å¯ã«ã¯å¿ èŠãããŸããïŒ:
interoperability/bindgen/libbirthday_wrapper.h:
#include "libbirthday.h"
interoperability/bindgen/Android.bp:
rust_bindgen {
name: "libbirthday_bindgen",
crate_name: "birthday_bindgen",
wrapper_src: "libbirthday_wrapper.h",
source_stem: "bindings",
static_libs: ["libbirthday"],
}
æåŸã«ãRust ããã°ã©ã ã§ãã€ã³ãã£ã³ã°ã䜿çšã§ããŸã:
interoperability/bindgen/Android.bp:
rust_binary {
name: "print_birthday_card",
srcs: ["main.rs"],
rustlibs: ["libbirthday_bindgen"],
static_libs: ["libbirthday"],
}
interoperability/bindgen/main.rs:
// Copyright 2022 Google LLC // SPDX-License-Identifier: Apache-2.0 //! Bindgen demo. use birthday_bindgen::{card, print_card}; fn main() { let name = std::ffi::CString::new("Peter").unwrap(); let card = card { name: name.as_ptr(), years: 42 }; // SAFETY: The pointer we pass is valid because it came from a Rust // reference, and the `name` it contains refers to `name` above which also // remains valid. `print_card` doesn't store either pointer to use later // after it returns. unsafe { print_card(&card); } }
-
Android ã®ãã«ãã«ãŒã«ã¯ãè£åŽã§èªåçã«
bindgenãåŒã³åºããŸãã -
mainå ã® Rust ã³ãŒãã¯ãäŸç¶ãšããŠæžãã®ãé£ããããšã«æ³šæããŠãã ãããåŒã³åºãå ã«å®å šãªã€ã³ã¿ãŒãã§ãŒã¹ãæäŸãã Rust ã©ã€ãã©ãªã®äžã«bindgenã®åºåãã«ãã»ã«åããã®ãããããã©ã¯ãã£ã¹ã§ãã
ãã€ããªã®å®è¡
ããã€ã¹äžã§ãã€ããªããã«ãããããã·ã¥ããŠå®è¡ããŸãã
m print_birthday_card
adb push "$ANDROID_PRODUCT_OUT/system/bin/print_birthday_card" /data/local/tmp
adb shell /data/local/tmp/print_birthday_card
æåŸã«ããã€ã³ãã£ã³ã°ãæ£ããåäœããããšã確èªããããã«ãèªåçæããããã¹ããå®è¡ã§ããŸãã
interoperability/bindgen/Android.bp:
rust_test {
name: "libbirthday_bindgen_test",
srcs: [":libbirthday_bindgen"],
crate_name: "libbirthday_bindgen_test",
test_suites: ["general-tests"],
auto_gen_config: true,
clippy_lints: "none", // Generated file, skip linting
lints: "none",
}
atest libbirthday_bindgen_test
ã·ã³ãã«ãª Rust ã©ã€ãã©ãª
Rust ã®é¢æ°ãåã C ã«ãšã¯ã¹ããŒãããã®ã¯ç°¡åã§ãã以äžã¯ã·ã³ãã«ãª Rust ã©ã€ãã©ãªã§ã:
interoperability/rust/libanalyze/analyze.rs
// Copyright 2025 Google LLC // SPDX-License-Identifier: Apache-2.0 //! Rust FFI demo. #![deny(improper_ctypes_definitions)] use std::os::raw::c_int; /// Analyze the numbers. // SAFETY: There is no other global function of this name. #[unsafe(no_mangle)] pub extern "C" fn analyze_numbers(x: c_int, y: c_int) { if x < y { println!("x ({x}) is smallest!"); } else { println!("y ({y}) is probably larger than x ({x})"); } }
interoperability/rust/libanalyze/Android.bp
rust_ffi {
name: "libanalyze_ffi",
crate_name: "analyze_ffi",
srcs: ["analyze.rs"],
include_dirs: ["."],
}
#[unsafe(no_mangle)] 㯠Rust ã®éåžžã®ååãã³ã°ãªã³ã°ãç¡å¹ã«ããããããšã¯ã¹ããŒãããã ã·ã³ãã«ã¯åã«é¢æ°åã«ãªããŸãã#[unsafe(export_name = "some_name")] ã䜿ã£ãŠ ä»»æã®ååãæå®ããããšãã§ããŸãã
Rust ã®åŒã³åºã
ããã§ãC ãã€ããªãããããåŒã³åºããããã«ãªããŸããã
interoperability/rust/libanalyze/analyze.h
#ifndef ANALYZE_H
#define ANALYZE_H
void analyze_numbers(int x, int y);
#endif
interoperability/rust/analyze/main.c
#include "analyze.h"
int main() {
analyze_numbers(10, 20);
analyze_numbers(123, 123);
return 0;
}
interoperability/rust/analyze/Android.bp
cc_binary {
name: "analyze_numbers",
srcs: ["main.c"],
static_libs: ["libanalyze_ffi"],
}
ãã€ããªããã«ãããããã€ã¹ã«ããã·ã¥ããŠå®è¡ããŸãã
m analyze_numbers
adb push "$ANDROID_PRODUCT_OUT/system/bin/analyze_numbers" /data/local/tmp
adb shell /data/local/tmp/analyze_numbers
C++ ãšã®çžäºéçš
CXX crate ã䜿ããšãRust ãš C++ ã®éã§å®å šã«çžäºéçšã§ããŸãã
å šäœçãªã¢ãããŒãã¯æ¬¡ã®ãšããã§ãã
ããªããžã¢ãžã¥ãŒã«
CXX ã§ã¯ãåèšèªããããäžæ¹ã®èšèªã«å
¬éããã颿°ã·ã°ããã£ã®èšè¿°ã å¿
èŠã§ãããã®èšè¿°ã¯ã#[cxx::bridge] 屿§ãã¯ããä»ãã Rust ã¢ãžã¥ãŒã«å
ã® extern ãããã¯ã䜿ã£ãŠæäŸããŸãã
// Copyright 2023 Google LLC
// SPDX-License-Identifier: Apache-2.0
#[allow(unsafe_op_in_unsafe_fn)]
#[cxx::bridge(namespace = "org::blobstore")]
mod ffi {
// Shared structs with fields visible to both languages.
struct BlobMetadata {
size: usize,
tags: Vec<String>,
}
// Rust types and signatures exposed to C++.
extern "Rust" {
type MultiBuf;
fn next_chunk(buf: &mut MultiBuf) -> &[u8];
}
// C++ types and signatures exposed to Rust.
unsafe extern "C++" {
include!("include/blobstore.h");
type BlobstoreClient;
fn new_blobstore_client() -> UniquePtr<BlobstoreClient>;
fn put(self: Pin<&mut BlobstoreClient>, parts: &mut MultiBuf) -> u64;
fn tag(self: Pin<&mut BlobstoreClient>, blobid: u64, tag: &str);
fn metadata(&self, blobid: u64) -> BlobMetadata;
}
}
- ããªããžã¯éåžžãã¯ã¬ãŒãå
ã®
ffiã¢ãžã¥ãŒã«ã§å®£èšããŸãã - ããªããžã¢ãžã¥ãŒã«å ã§è¡ã£ã宣èšãããCXX ã¯å¯Ÿå¿ãã Rust ãš C++ ã® å/颿°å®çŸ©ãçæãããããã®é ç®ãäž¡æ¹ã®èšèªã«å ¬éããŸãã
- çæããã Rust ã³ãŒãã確èªããã«ã¯ãcargo-expand ã䜿ã£ãŠå±éããã proc macro ã衚瀺ããŸããã»ãšãã©ã®äŸã§ã¯ã
ffiã¢ãžã¥ãŒã«ã ããå±éããããã«cargo expand ::ffiã䜿çšããŸãïŒãã ãããã㯠Android ãããžã§ã¯ãã«ã¯åœãŠã¯ãŸããŸããïŒã - çæããã C++ ã³ãŒãã確èªããã«ã¯ã
target/cxxbridgeãåç §ããŠãã ããã
Rust ããªããžå®£èš
// èäœæš© 2023 Google LLC
// SPDX-License-Identifier: Apache-2.0
#[cxx::bridge]
mod ffi {
extern "Rust" {
type MyType; // Opaque type
fn foo(&self); // Method on `MyType`
fn bar() -> Box<MyType>; // Free function
}
}
struct MyType(i32);
impl MyType {
fn foo(&self) {
println!("{}", self.0);
}
}
fn bar() -> Box<MyType> {
Box::new(MyType(123))
}
extern "Rust"ã§å®£èšãããé ç®ã¯ã芪ã¢ãžã¥ãŒã«ã§ã¹ã³ãŒãå ã«ããé ç®ãåç §ããŸãã- CXX ã³ãŒããžã§ãã¬ãŒã¿ã¯ã察å¿ãã C++ 宣èšãå«ã C++ ããããŒãã¡ã€ã«ãçæããããã«ã
extern "Rust"ã»ã¯ã·ã§ã³ã䜿çšããŸããçæãããããããŒã¯ãããªããžãå«ã Rust ãœãŒã¹ãã¡ã€ã«ãšåããã¹ãæã¡ãŸããããã¡ã€ã«æ¡åŒµåã¯.rs.hã«ãªããŸãã
çæããã C++
// Copyright 2023 Google LLC
// SPDX-License-Identifier: Apache-2.0
#[cxx::bridge]
mod ffi {
// Rust types and signatures exposed to C++.
extern "Rust" {
type MultiBuf;
fn next_chunk(buf: &mut MultiBuf) -> &[u8];
}
}
ããããæ¬¡ã®ãã㪠C++ ãçæãããŸãã
struct MultiBuf final : public ::rust::Opaque {
~MultiBuf() = delete;
private:
friend ::rust::layout;
struct layout {
static ::std::size_t size() noexcept;
static ::std::size_t align() noexcept;
};
};
::rust::Slice<::std::uint8_t const> next_chunk(::org::blobstore::MultiBuf &buf) noexcept;
C++ ããªããžå®£èš
// èäœæš© 2023 Google LLC
// SPDX-License-Identifier: Apache-2.0
#[cxx::bridge]
mod ffi {
// C++ types and signatures exposed to Rust.
unsafe extern "C++" {
include!("include/blobstore.h");
type BlobstoreClient;
fn new_blobstore_client() -> UniquePtr<BlobstoreClient>;
fn put(self: Pin<&mut BlobstoreClient>, parts: &mut MultiBuf) -> u64;
fn tag(self: Pin<&mut BlobstoreClient>, blobid: u64, tag: &str);
fn metadata(&self, blobid: u64) -> BlobMetadata;
}
}
ããã«ãããïŒããããïŒæ¬¡ã®ãã㪠Rust ãçæãããŸã:
// èäœæš© 2023 Google LLC
// SPDX-License-Identifier: Apache-2.0
#[repr(C)]
pub struct BlobstoreClient {
_private: ::cxx::private::Opaque,
}
pub fn new_blobstore_client() -> ::cxx::UniquePtr<BlobstoreClient> {
extern "C" {
#[link_name = "org$blobstore$cxxbridge1$new_blobstore_client"]
fn __new_blobstore_client() -> *mut BlobstoreClient;
}
unsafe { ::cxx::UniquePtr::from_raw(__new_blobstore_client()) }
}
impl BlobstoreClient {
pub fn put(&self, parts: &mut MultiBuf) -> u64 {
extern "C" {
#[link_name = "org$blobstore$cxxbridge1$BlobstoreClient$put"]
fn __put(
_: &BlobstoreClient,
parts: *mut ::cxx::core::ffi::c_void,
) -> u64;
}
unsafe {
__put(self, parts as *mut MultiBuf as *mut ::cxx::core::ffi::c_void)
}
}
}
// ...
- ããã°ã©ããŒã¯ãèªåã§èšè¿°ããã·ã°ããã£ãæ£ç¢ºã§ããããšãä¿èšŒããå¿ èŠã¯ãããŸãããCXX ã¯ããã®ã·ã°ããã£ã C++ ã§å®£èšããããã®ãšå®å šã«å¯Ÿå¿ããŠããããšããéçã¢ãµãŒã·ã§ã³ã«ãã£ãŠæ€èšŒããŸãã
unsafe externãããã¯ã䜿ããšãRust ããå®å šã«åŒã³åºãã C++ 颿°ã宣èšã§ããŸãã
å ±æå
// Copyright 2023 Google LLC
// SPDX-License-Identifier: Apache-2.0
#[cxx::bridge]
mod ffi {
#[derive(Clone, Debug, Hash)]
struct PlayingCard {
suit: Suit,
value: u8, // A=1, J=11, Q=12, K=13
}
enum Suit {
Clubs,
Diamonds,
Hearts,
Spades,
}
}
- ãµããŒããããŠããã®ã¯ C ã©ã€ã¯ãªïŒãŠãããïŒåæåã®ã¿ã§ãã
- å
±æåã«å¯Ÿãã
#[derive()]ã§ã¯ããµããŒãããããã¬ã€ãã¯éãããŠããŸãã 察å¿ããæ©èœã¯ C++ ã³ãŒãã«å¯ŸããŠãçæãããŸããããšãã°ãHashã derive ãããšã察å¿ãã C++ åã«å¯Ÿããstd::hashã® å®è£ ãçæãããŸãã
å ±æåæå
// Copyright 2023 Google LLC
// SPDX-License-Identifier: Apache-2.0
#[cxx::bridge]
mod ffi {
enum Suit {
Clubs,
Diamonds,
Hearts,
Spades,
}
}
çæããã Rust:
#![allow(unused)] fn main() { // Copyright 2023 Google LLC // SPDX-License-Identifier: Apache-2.0 #[derive(Copy, Clone, PartialEq, Eq)] #[repr(transparent)] pub struct Suit { pub repr: u8, } #[allow(non_upper_case_globals)] impl Suit { pub const Clubs: Self = Suit { repr: 0 }; pub const Diamonds: Self = Suit { repr: 1 }; pub const Hearts: Self = Suit { repr: 2 }; pub const Spades: Self = Suit { repr: 3 }; } }
çæããã C++:
enum class Suit : uint8_t {
Clubs = 0,
Diamonds = 1,
Hearts = 2,
Spades = 3,
};
- Rust åŽã§ã¯ãå ±æåæåçšã«çæãããã³ãŒãã¯ãå®éã«ã¯æ°å€ãã©ãããã struct ã§ããããã¯ãC++ ã§ã¯ enum class ãåæãããŠããã©ã®ããªã¢ã³ããšãç°ãªãå€ãä¿æããŠããŠã UB ã«ã¯ãªãããRust åŽã®è¡šçŸãåãæ¯ãèããæã€å¿ èŠãããããã§ãã
Rust ã®ãšã©ãŒãã³ããªã³ã°
// Copyright 2023 Google LLC
// SPDX-License-Identifier: Apache-2.0
#[cxx::bridge]
mod ffi {
extern "Rust" {
fn fallible(depth: usize) -> Result<String>;
}
}
fn fallible(depth: usize) -> anyhow::Result<String> {
if depth == 0 {
return Err(anyhow::Error::msg("fallible1 requires depth > 0"));
}
Ok("Success!".into())
}
Resultãè¿ã Rust 颿°ã¯ãC++ åŽã§ã¯äŸå€ã«å€æãããŸãã- ã¹ããŒãããäŸå€ã¯åžžã«
rust::Erroråã§ãããäž»ã«ãšã©ãŒã¡ãã»ãŒãžæååãååŸããææ®µãæäŸããŸãããšã©ãŒã¡ãã»ãŒãžã¯ããšã©ãŒåã®Displayimpl ããååŸãããŸãã - Rust ãã C++ ãž panic ãã¢ã³ã¯ã€ã³ãããããšãããã»ã¹ã¯åžžã«å³åº§ã«çµäºããŸãã
C++ ã®ãšã©ãŒåŠç
// èäœæš© 2023 Google LLC
// SPDX-License-Identifier: Apache-2.0
#[cxx::bridge]
mod ffi {
unsafe extern "C++" {
include!("example/include/example.h");
fn fallible(depth: usize) -> Result<String>;
}
}
fn main() {
if let Err(err) = ffi::fallible(99) {
eprintln!("Error: {}", err);
process::exit(1);
}
}
Resultãè¿ãããã«å®£èšããã C++ 颿°ã¯ãC++ åŽã§ã¹ããŒãããããããäŸå€ãææããåŒã³åºãå ã® Rust 颿°ã«Errå€ãšããŠè¿ããŸããResultãè¿ãããã« CXX ããªããžã§å®£èšãããŠããªãextern "C++"颿°ããäŸå€ãã¹ããŒãããå Žåãããã°ã©ã 㯠C++ ã®std::terminateãåŒã³åºããŸãããã®åäœã¯ãåãäŸå€ãnoexceptC++ 颿°ãéããŠã¹ããŒãããå Žåãšåçã§ãã
远å ã®å
| Rust ã®å | C++ ã®å |
|---|---|
String | rust::String |
&str | rust::Str |
CxxString | std::string |
&[T]/&mut [T] | rust::Slice |
Box<T> | rust::Box<T> |
UniquePtr<T> | std::unique_ptr<T> |
Vec<T> | rust::Vec<T> |
CxxVector<T> | std::vector<T> |
- ãããã®åã¯ãå ±ææ§é äœã®ãã£ãŒã«ããããã³ extern 颿°ã®åŒæ°ãšæ»ãå€ã§äœ¿çšã§ããŸãã
- Rust ã®
Stringã¯std::stringã«çŽæ¥ããããããªãããšã«æ³šæããŠãã ãããããã«ã¯ããã€ãã®çç±ããããŸããstd::stringã¯ãStringãèŠæ±ãã UTF-8 äžå€æ¡ä»¶ãç¶æããŸããã- ãã® 2 ã€ã®åã¯ã¡ã¢ãªäžã®ã¬ã€ã¢ãŠããç°ãªããããèšèªéã§çŽæ¥åãæž¡ãããšã¯ã§ããŸããã
std::stringã«ã¯ Rust ã®ã ãŒãã»ãã³ãã£ã¯ã¹ãšäžèŽããªãã ãŒãã³ã³ã¹ãã©ã¯ã¿ãŒãå¿ èŠãªãããstd::stringã倿ž¡ãã§ Rust ã«æž¡ãããšã¯ã§ããŸããã
Android ã§ã®ãã«ã
2 ã€ã® genrule ãäœæããŸãã1 ã€ã¯ CXX ããããŒãçæãããã 1 ã€ã¯ CXX ãœãŒã¹ãã¡ã€ã«ãçæããŸãããããã¯ãã®åŸãcc_library_static ãžã®å
¥åãšããŠäœ¿çšãããŸãã
// lib.rs å
ã® Rust ããšã¯ã¹ããŒããã颿°ã«å¯Ÿãã
// C++ ãã€ã³ãã£ã³ã°ãå«ã C++ ããããŒãçæããã
genrule {
name: "libcxx_test_bridge_header",
tools: ["cxxbridge"],
cmd: "$(location cxxbridge) $(in) --header > $(out)",
srcs: ["lib.rs"],
out: ["lib.rs.h"],
}
// Rust ãåŒã³åºã C++ ã³ãŒããçæããã
genrule {
name: "libcxx_test_bridge_code",
tools: ["cxxbridge"],
cmd: "$(location cxxbridge) $(in) > $(out)",
srcs: ["lib.rs"],
out: ["lib.rs.cc"],
}
cxxbridgeããŒã«ã¯ãããªããžã¢ãžã¥ãŒã«ã® C++ åŽãçæããã¹ã¿ã³ãã¢ãã³ããŒã«ã§ãããã㯠Android ã«å«ãŸããŠãããSoong ããŒã«ãšããŠå©çšã§ããŸãã- æ
£äŸãšããŠãRust ã®ãœãŒã¹ãã¡ã€ã«ã
lib.rsã®å ŽåãããããŒãã¡ã€ã«åã¯lib.rs.hããœãŒã¹ãã¡ã€ã«åã¯lib.rs.ccã«ãªããŸãããã ãããã®åœåèŠåã¯åŒ·å¶ãããŸããã
Android ã§ã®ãã«ã
CXX ãçæããããããŒãšãœãŒã¹ãã¡ã€ã«ãå«ããŠãC++ ã©ã€ãã©ãªããã«ãããããã® cc_library_static ãäœæããŸãã
cc_library_static {
name: "libcxx_test_cpp",
srcs: ["cxx_test.cpp"],
generated_headers: [
"cxx-bridge-header",
"libcxx_test_bridge_header"
],
generated_sources: ["libcxx_test_bridge_code"],
}
libcxx_test_bridge_headerãšlibcxx_test_bridge_codeã¯ãCXX ãçæãã C++ ãã€ã³ãã£ã³ã°ã®äŸåé¢ä¿ã§ããããšã説æããŸãããããã®èšå®æ¹æ³ã¯æ¬¡ã®ã¹ã©ã€ãã§ç€ºããŸãã- å
±éã® CXX å®çŸ©ãåã蟌ãããã«ã
cxx-bridge-headerã©ã€ãã©ãªã«ãäŸåããå¿ èŠãããããšã«æ³šæããŠãã ããã - Android ã§ CXX ã䜿çšããããã®å®å šãªããã¥ã¡ã³ã㯠the Android docs ã«ãããŸããä»åŸãåè¬è ããããã®æé ãåã³åç §ã§ããå Žæããããããã«ããã®ãªã³ã¯ãã¯ã©ã¹ã«å ±æãããšããã§ãããã
Android ã§ã®ãã«ã
libcxx ãšç¬èªã® cc_library_static ã«äŸåãã rust_binary ãäœæããŸãã
rust_binary {
name: "cxx_test",
srcs: ["lib.rs"],
rustlibs: ["libcxx"],
static_libs: ["libcxx_test_cpp"],
}
Javaãšã®çžäºéçšæ§
Java㯠Java Native Interface (JNI) ãä»ããŠå
±æãªããžã§ã¯ããèªã¿èŸŒããŸãã jni ã¯ã¬ãŒãã䜿ããšãäºææ§ã®ãã ã©ã€ãã©ãªãäœæã§ããŸãã
ãŸããJavaã«ãšã¯ã¹ããŒãããRust颿°ãäœæããŸã:
interoperability/java/src/lib.rs:
#![allow(unused)] fn main() { // èäœæš© 2022 Google LLC // SPDX-License-Identifier: Apache-2.0 //! Rust <-> Java FFI demo. use jni::JNIEnv; use jni::objects::{JClass, JString}; use jni::sys::jstring; /// HelloWorld::hello method implementation. // SAFETY: There is no other global function of this name. #[unsafe(no_mangle)] pub extern "system" fn Java_HelloWorld_hello( mut env: JNIEnv, _class: JClass, name: JString, ) -> jstring { let input: String = env.get_string(&name).unwrap().into(); let greeting = format!("Hello, {input}!"); let output = env.new_string(greeting).unwrap(); output.into_raw() } }
interoperability/java/Android.bp:
rust_ffi_shared {
name: "libhello_jni",
crate_name: "hello_jni",
srcs: ["src/lib.rs"],
rustlibs: ["libjni"],
}
次ã«ããã®é¢æ°ãJavaããåŒã³åºããŸã:
interoperability/java/HelloWorld.java:
class HelloWorld {
private static native String hello(String name);
static {
System.loadLibrary("hello_jni");
}
public static void main(String[] args) {
String output = HelloWorld.hello("Alice");
System.out.println(output);
}
}
interoperability/java/Android.bp:
java_binary {
name: "helloworld_jni",
srcs: ["HelloWorld.java"],
main_class: "HelloWorld",
jni_libs: ["libhello_jni"],
}
æåŸã«ããã€ããªããã«ããåæãå®è¡ã§ããŸã:
m helloworld_jni
adb sync # requires adb root && adb remount
adb shell /system/bin/helloworld_jni
-
unsafe(no_mangle)屿§ã¯ãRustã«Java_HelloWorld_helloã·ã³ãã«ãæžããããšããã«åºåããããæç€ºããŸããããã¯ã Javaããã®ã·ã³ãã«ãHelloWorldã¯ã©ã¹ã®helloã¡ãœãããšããŠèªèã§ããããã«ããããã«éèŠã§ãã- ããã©ã«ãã§ã¯ãRustã¯ã·ã³ãã«ããã³ã°ã«ïŒåå倿ŽïŒããããã1ã€ã®ãã€ããªã« åãRustã¯ã¬ãŒãã®2ã€ã®ããŒãžã§ã³ããªã³ã¯ã§ããŸãã
Chromium ã«ããã Rust ãžãããã
Chromium ã§ã¯ãµãŒãããŒã㣠ã©ã€ãã©ãªã§ Rust ããµããŒããããŠãããRust ãšæ¢åã® Chromium C++ ã³ãŒããæ¥ç¶ããããã®ãã¡ãŒã¹ãããŒãã£ã®ã°ã«ãŒ ã³ãŒããçšæãããŠããŸãã
仿¥ã¯ãRust ãåŒã³åºããŠæååã§ã¡ãã£ãšã°ãããããšãããŠã¿ãŸããããã³ãŒãã®ã©ããã§ UTF-8 æååããŠãŒã¶ãŒã«è¡šç€ºããŠããç®æããããªãã ããã§èª¬æããæ£ç¢ºãªç®æã§ã¯ãªããã³ãŒãããŒã¹å ã®ãã®éšåã§ãã®æé ã«åŸã£ãŠã¿ãŠãã ããã
ã»ããã¢ãã
Chromium ããã«ãããŠå®è¡ã§ããããšã確èªããŠãã ãããã³ãŒããæ¯èŒçæ°ãããã°ãã©ã®ãã©ãããã©ãŒã ããã³ã©ã®ãã«ããã©ã°ã®çµã¿åããã§ã åé¡ãããŸããïŒã³ãããããžã·ã§ã³ 1223636 以éãããªãã¡ 2023 幎 11 æã«å¯Ÿå¿ïŒ:
gn gen out/Debug
autoninja -C out/Debug chrome
out/Debug/chrome # ãŸã㯠Mac ã§ã¯ãout/Debug/Chromium.app/Contents/MacOS/Chromium
ïŒå埩æéãæçã«ãããããcomponent ã® debug ãã«ããæšå¥šããŸãããã㯠ããã©ã«ãã§ãïŒïŒ
ãŸã ãã®æ®µéã«éããŠããªãå Žåã¯ã How to build Chromium ãåç §ããŠãã ãããæ³šæ: Chromium ããã«ãã§ããããã«ã»ããã¢ããããã«ã¯ æéãããããŸãã
ãŸããVisual Studio code ãã€ã³ã¹ããŒã«ããŠããããšãæšå¥šããŸãã
æŒç¿ã«ã€ããŠ
ã³ãŒã¹ã®ãã®ããŒãã«ã¯ãäºãã«ç©ã¿éãªãäžé£ã®æŒç¿ããããŸãã ãããã¯æåŸã«ãŸãšããŠè¡ãã®ã§ã¯ãªããã³ãŒã¹å šäœãéããŠåæ£ããŠé²ããŸãããã ããéšåãå®äºããæéããªããŠããå¿é ã¯ãããŸãããæ¬¡ã®æéæ 㧠远ãã€ãããšãã§ããŸãã
Chromium ãš Cargo ã®ãšã³ã·ã¹ãã ã®æ¯èŒ
Rust ã³ãã¥ããã£ã§ã¯ãéåžž cargo ãš crates.io ã®ã©ã€ãã©ãªã䜿ããŸãã Chromium 㯠gn ãš ninjaãããã³å³éžãããäŸåé¢ä¿ã»ããã䜿ã£ãŠãã«ããããŸãã
Rust ã§ã³ãŒããæžããšãã®éžæè¢ã¯æ¬¡ã®ãšããã§ãã
//build/rust/*.gniã®ãã³ãã¬ãŒãã®å©ããåããŠgnãšninjaã䜿ã ïŒããšãã°ãåŸã§ç»å Žããrust_static_libraryãªã©ïŒããã®æ¹æ³ã§ã¯ãChromium ã® ç£æ»æžã¿ããŒã«ãã§ãŒã³ãšã¯ã¬ãŒãã䜿ããŸããcargoã䜿ãããã ãã Chromium ã®ç£æ»æžã¿ããŒã«ãã§ãŒã³ãšã¯ã¬ãŒãã«éå®ããcargoã䜿ããããŒã«ãã§ãŒã³ ã ã€ã³ã¿ãŒãããããããŠã³ããŒãããã¯ã¬ãŒã ãä¿¡é Œãã
ããããå
㯠gn ãš ninja ã«çŠç¹ãåœãŠãŸããããã¯ãRust ã® ã³ãŒãã Chromium ãã©ãŠã¶ã«çµã¿èŸŒãã§ãã«ãããæ¹æ³ã ããã§ããåæã«ãCargo 㯠Rust ãšã³ã·ã¹ãã ã®éèŠãªäžéšã§ãããããŒã«ããã¯ã¹ã«å
¥ããŠããã¹ããã®ã§ãã
ããæŒç¿
å°äººæ°ã®ã°ã«ãŒãã«åãããŠã次ãè¡ã£ãŠãã ããã
cargoãå©ç¹ãããããå¯èœæ§ã®ããã·ããªãªããã¬ã€ã³ã¹ããŒãã³ã°ãããããã®ã·ããªãªã®ãªã¹ã¯ ãããã¡ã€ã«ãè©äŸ¡ãããgnãšninjaããªãã©ã€ã³ã®cargoãªã©ã䜿ããšãã«ãã©ã®ããŒã«ãã©ã€ãã©ãªã人ã ã®éå£ã ä¿¡é Œããå¿ èŠãããããè°è«ããã
åŠçã«ã¯ãæŒç¿ãçµããåã«ã¹ããŒã«ãŒããŒããçã¿èŠããªãããã«äŒããŠãã ããã åè¬è ãç©ççã«åãå Žæã«ããåæã§ã3ã4 人ã®å°ã°ã«ãŒãã§è°è«ããããã«ä¿ããŠãã ããã
æŒç¿ã®ååïŒãCargo ãå©ç¹ãããããå¯èœæ§ãããã·ããªãªãïŒã«é¢ããã¡ã¢/ãã³ã:
-
ããŒã«ãæžããããChromium ã®äžéšããããã¿ã€ãã³ã°ããããããšãã«ã crates.io ã©ã€ãã©ãªã®è±ããªãšã³ã·ã¹ãã ã«ã¢ã¯ã»ã¹ã§ããã®ã¯çŽ æŽãããããšã§ããã»ãšãã©äœã«ã§ã察å¿ããã¯ã¬ãŒããããã éåžžã¯ãšãŠãå¿«é©ã«äœ¿ããŸããïŒã³ãã³ãã©ã€ã³è§£æçšã®
clapãããŸããŸãª ãã©ãŒããããžã®ã·ãªã¢ã©ã€ãº/ãã·ãªã¢ã©ã€ãºçšã®serdeãã€ãã¬ãŒã¿ãæ±ãããã®itertoolsãªã©ïŒãcargoã䜿ããšãã©ã€ãã©ãªãç°¡åã«è©ŠããŸãïŒCargo.tomlã« 1 è¡è¿œå ããŠã ã³ãŒããæžãå§ããã ãã§ãïŒ- CPAN ã
perlãäžè¬çãªéžæè¢ã«ããå©ããšãªã£ãããšãšã®æ¯èŒã¯æçãããããŸããããããã¯ãpython+pipãšæ¯èŒããŠãããã§ãããã
-
éçºäœéšãéåžžã«è¯ããã®ã«ãªã£ãŠããã®ã¯ãRust ã®äžæ žããŒã«ã ãã«ãããã®ã§ã¯ãããŸããïŒããšãã°ã nightlyãçŸåšã® stableãå€ã stable ã§åäœããå¿ èŠãããã¯ã¬ãŒãããã¹ããããšãã«ã
rustupã䜿ã£ãŠå¥ã®rustcããŒãžã§ã³ã«åãæ¿ããããšãªã©ïŒãããã«å ããŠã ãµãŒãããŒãã£ãŒããŒã«ã®ãšã³ã·ã¹ãã ããããŸãïŒããšãã° Mozilla ã¯ãã»ãã¥ãªãã£ç£æ»ã®å¹çåãšå ±æã®ããã«cargo vetãæäŸããŠãããcriterionã¯ã¬ãŒã㯠ãã³ãããŒã¯ãå®è¡ããããã®ç°¡äŸ¿ãªæ¹æ³ãæäŸããŸãïŒãcargoã䜿ããšãcargo install --locked cargo-vetã§ããŒã«ãç°¡åã«è¿œå ã§ããŸãã- Chrome Extensions ã VScode æ¡åŒµæ©èœãšã®æ¯èŒãæçãããããŸããã
-
cargoãé©åãªéžæè¢ã«ãªããããããžã§ã¯ãã®ãåºç¯ã§äžè¬çãªäŸ:- æå€ãããããŸããããRust ã¯ã³ãã³ãã©ã€ã³ããŒã«ãæžãããã®èšèªãšããŠã æ¥çã§ãŸããŸã人æ°ãé«ãŸã£ãŠããŸããã©ã€ãã©ãªã®åºããšäœ¿ãåæã¯ Python ã«å¹æµãã€ã€ãããå ç¢ã§ããïŒè±ããªåã·ã¹ãã ã®ãããïŒã å®è¡é床ãéãã§ãïŒã€ã³ã¿ããªã¿èšèªã§ã¯ãªããã³ã³ãã€ã«èšèªã§ããããïŒã
- Rust ãšã³ã·ã¹ãã ã«åå ããã«ã¯ãCargo ã®ãããªæšæºç㪠Rust ããŒã«ã䜿ãå¿ èŠããããŸãã å€éšããã®ã³ã³ããªãã¥ãŒã·ã§ã³ãåãããã©ã€ãã©ãªãã Chromium ã®å€éšã§ã䜿ããããã©ã€ãã©ãªïŒããšãã° Bazel ã Android/Soong ã®ãã«ãç°å¢ïŒ ã§ã¯ Cargo ã䜿ãã¹ãã§ãã
-
cargoããŒã¹ã® Chromium é¢é£ãããžã§ã¯ãã®äŸ:serde_json_lenientïŒGoogle ã®ä»ã®éšåã§è©Šéšçã«äœ¿ããã ããã©ãŒãã³ã¹æ¹åãå«ã PR ã«ã€ãªãããŸããïŒfont-typesã®ãã㪠Fontations ã©ã€ãã©ãªgnrtããŒã«ïŒãã®ã³ãŒã¹ã®åŸåã§ç»å ŽããŸãïŒã§ãã³ãã³ãã©ã€ã³è§£æã«clapããèšå®ãã¡ã€ã«ã«tomlãå©çšããŠããŸãã- å
責äºé
:
cargoã䜿ãç¹æã®çç±ã® 1 ã€ã¯ãRust ããŒã«ãã§ãŒã³ããã«ãããéã« Rust æšæºã©ã€ãã©ãªããã«ãããã³ããŒãã¹ãã©ãããããšããgnãå©çšã§ããªãã£ãããšã§ãã run_gnrt.py㯠Chromium ã®cargoãšrustcã®ã³ããŒã䜿ããŸããgnrt㯠ã€ã³ã¿ãŒãããããããŠã³ããŒããããµãŒãããŒãã£ãŒã©ã€ãã©ãªã«äŸåããŠããŸãããrun_gnrt.pyã¯cargoã«å¯ŸããŠãCargo.lockã«ãã£ãŠ--lockedã®å 容ã®ã¿ãèš±å¯ããããæ±ããŸããïŒ
- å
責äºé
:
åŠçã¯ã以äžã®é ç®ãæé»çãŸãã¯æç€ºçã«ä¿¡é ŒãããŠãããã®ã ãšç¹å®ãããããããŸããã
rustcïŒRust ã³ã³ãã€ã©ïŒãããèªäœã LLVM ã©ã€ãã©ãªãClang ã³ã³ãã€ã©ãrustcã®ãœãŒã¹ïŒGitHub ããååŸãããRust compiler team ã«ãã£ãŠã¬ãã¥ãŒãããïŒãããã³ããŒãã¹ãã©ããçšã«ããŠã³ããŒãããããã€ã㪠Rust ã³ã³ãã€ã©ã«äŸåããŠããŸãrustupïŒrustup㯠https://github.com/rust-lang/ çµç¹ã®åäžã§éçºãããŠããããšã ã€ãŸãrustcãšåãã§ããããšãææãããšãããããããŸããïŒcargoãrustfmtãªã©- ããŸããŸãªå
éšã€ã³ãã©ã¹ãã©ã¯ãã£ïŒ
rustcããã«ãããããããäºåãã«ãæžã¿ããŒã«ãã§ãŒã³ã Chromium ãšã³ãžãã¢ã«é åžããã·ã¹ãã ãªã©ïŒ cargo auditãcargo vetãªã©ã® Cargo ããŒã«//third_party/rustã« vendored ããã Rust ã©ã€ãã©ãªïŒ security@chromium.org ã«ããç£æ»æžã¿ïŒ- ãã®ä»ã® Rust ã©ã€ãã©ãªïŒäžéšã¯ãããã§ãäžéšã¯ããªã人æ°ãããåºã䜿ãããŠããŸãïŒ
Chromium ã® Rust ããªã·ãŒ
Chromium ã® Rust ããªã·ãŒã¯ ãã¡ãã«ãããŸãã Rust ã¯ãã¡ãŒã¹ãããŒãã£ã³ãŒããšãµãŒãããŒãã£ã³ãŒãã®äž¡æ¹ã«äœ¿çšã§ããŸãã
çŽç²ãªãã¡ãŒã¹ãããŒãã£ã³ãŒãã« Rust ã䜿çšããå Žåã¯ã次ã®ããã«ãªããŸãã
ãµãŒãããŒãã£ã®ã±ãŒã¹ãäžè¬çã§ããéåžžã¯å°éã®ãã¡ãŒã¹ãããŒãã£ã® ã°ã«ãŒã³ãŒããå¿ èŠã«ãªããŸããRust ã©ã€ãã©ãªã§ C/C++ API ãçŽæ¥å ¬éããŠãããã®ã¯ ãããããã ããã§ãã
ãµãŒãããŒãã£ã® crate ã䜿çšããã·ããªãªã®æ¹ãããè€éãªãããæ¬æ¥ã® ã³ãŒã¹ã§ã¯æ¬¡ã®ç¹ã«éç¹ã眮ããŸãã
- ãµãŒãããŒãã£ã® Rust ã©ã€ãã©ãªïŒãcrateãïŒãåã蟌ãããš
- Chromium ã® C++ ãããããã® crate ã䜿çšã§ããããã«ããããã®ã°ã«ãŒã³ãŒããæžãããšãïŒåã ææ³ã¯ããã¡ãŒã¹ãããŒãã£ã® Rust ã³ãŒããæ±ãå Žåã«ã䜿ãããŸãïŒã
ãã«ãã«ãŒã«
Rust ã³ãŒãã¯éåžž cargo ã䜿ã£ãŠãã«ãããŸããChromium ã¯ãå¹çã®ããã« gn ãš ninja ã§ãã«ãããŸã â ãã®éçã«ãŒã«ã«ãããæå€§éã®äžŠåæ§ãå¯èœã«ãªããŸããRust ã äŸå€ã§ã¯ãããŸããã
Chromium ã« Rust ã³ãŒãã远å ãã
æ¢åã® Chromium ã® BUILD.gn ãã¡ã€ã«ã®ããããã§ãrust_static_library ã宣èšããŸã:
import("//build/rust/rust_static_library.gni")
rust_static_library("my_rust_lib") {
crate_root = "lib.rs"
sources = [ "lib.rs" ]
}
ä»ã® Rust ã¿ãŒã²ããã«å¯Ÿãã deps ã远å ããããšãã§ããŸããåŸã§ãããã䜿ã£ãŠ ãµãŒãããŒãã£ã³ãŒãã«äŸåããããã«ããŸãã
crate ã«ãŒã ãš ãœãŒã¹ã®å®å
šãªäžèЧ ã® äž¡æ¹ ãæå®ããªããã°ãªããŸããã crate_root ã¯ãã³ã³ãã€ã«åäœã®ã«ãŒããã¡ã€ã«ã衚ããRust ã³ã³ãã€ã©ã«æž¡ããããã¡ã€ã«ã§ã â é垞㯠lib.rs ã§ããsources ã¯ãåãã«ããå¿
èŠãªã¿ã€ãã³ã°ã ninja ã å€å®ããããã«å¿
èŠãªããã¹ãŠã®ãœãŒã¹ãã¡ã€ã«ã®å®å
šãªäžèЧã§ãã
ïŒRust ã«ã¯ source_set ãšãããã®ã¯ãããŸããããªããªããRust ã§ã¯ crate å
šäœã ã³ã³ãã€ã«åäœã ããã§ããstatic_library ãæå°åäœã§ããïŒ
gn ã® Rust éçã©ã€ãã©ãªåãçµã¿èŸŒã¿ãµããŒã ã䜿ãã®ã§ã¯ãªãããªã gn ãã³ãã¬ãŒããå¿ èŠãªã®ãçåã«æã人ããããããããŸããããã®çãã¯ããã® ãã³ãã¬ãŒãã CXX çžäºéçšãRust ã® featureããŠããããã¹ãããµããŒãããŠããã ãã®åŸãã®äžéšã䜿ãããã§ãã
unsafe Rustã³ãŒããå«ãã
Unsafe Rustã³ãŒãã¯ãããã©ã«ãã§ã¯ rust_static_library ã§çŠæ¢ãããŠããŸã â ã³ã³ãã€ã«ãããŸãããUnsafe Rustã³ãŒããå¿
èŠãªå Žåã¯ãgnã¿ãŒã²ããã« allow_unsafe = true ã远å ããŠãã ãããïŒãã®ã³ãŒã¹ã®åŸåã§ããããå¿
èŠã«ãªãç¶æ³ãèŠãŠãããŸããïŒ
import("//build/rust/rust_static_library.gni")
rust_static_library("my_rust_lib") {
crate_root = "lib.rs"
sources = [
"lib.rs",
"hippopotamus.rs"
]
allow_unsafe = true
}
Chromium C++ ãã Rust ã³ãŒãã«äŸåãã
äžèšã®ã¿ãŒã²ããããããããã® Chromium C++ ã¿ãŒã²ããã® deps ã«è¿œå ããã ãã§ãã
import("//build/rust/rust_static_library.gni")
rust_static_library("my_rust_lib") {
crate_root = "lib.rs"
sources = [ "lib.rs" ]
}
# ãŸã㯠source_setãstatic_library ãªã©ã
component("preexisting_cpp") {
deps = [ ":my_rust_lib" ]
}
Visual Studio Code
Rust ã³ãŒãã§ã¯åãçç¥ããããããåªãã IDE 㯠C++ ã®å Žå以äžã«æçšã§ããChromium ã® Rust éçºã§ã¯ Visual Studio Code ãããŸãæ©èœããŸãã䜿çšããã«ã¯ã次ã®ããã«ããŸãã
- VSCode ã«ã以åã®åœ¢åŒã® Rust ãµããŒãã§ã¯ãªãã
rust-analyzeræ¡åŒµæ©èœãå ¥ã£ãŠããããšã確èªãã gn gen out/Debug --export-rust-projectãå®è¡ããïŒãŸãã¯åºåãã£ã¬ã¯ããªã«å¿ããåçã®ã³ãã³ãïŒln -s out/Debug/rust-project.json rust-project.json
èŽè¡ã IDE ã«å¯ŸããŠæççã«ãªããã¡ãªå Žåã¯ãrust-analyzer ã®ã³ãŒãæ³šéæ©èœãæ¢çŽ¢æ©èœã®ããã€ãããã¢ãããšå¹æçãããããŸããã
以äžã®æé ã¯ãã¢ã®å©ãã«ãªããããããŸããïŒãã ãã代ããã«èªåãæãããç¥ã£ãŠãã Chromium é¢é£ã® Rust ã³ãŒãã䜿ã£ãŠãæ§ããŸããïŒã
components/qr_code_generator/qr_code_generator_ffi_glue.rsãéãqr_code_generator_ffi_glue.rså ã®QrCode::newåŒã³åºãïŒ26 è¡ç®ä»è¿ïŒã«ã«ãŒãœã«ã眮ã- ããã¥ã¡ã³ãã衚瀺 ããã¢ããïŒäžè¬çãªããŒãã€ã³ã: vscode = ctrl k i; vim/CoC = KïŒã
- å®çŸ©ãžç§»å ããã¢ããïŒäžè¬çãªããŒãã€ã³ã: vscode = F12; vim/CoC = g dïŒã ïŒããã«ãã
//third_party/rust/.../qr_code-.../src/lib.rsã«ç§»åããŸããïŒ - ã¢ãŠãã©ã€ã³ ããã¢ãã
QrCode::with_bitsã¡ãœããïŒ164 è¡ç®ä»è¿ïŒãžç§»åãã ïŒã¢ãŠãã©ã€ã³ã¯ vscode ã®ãã¡ã€ã«ãšã¯ã¹ãããŒã©ãŒãã€ã³å ã«ãããŸããvim/CoC ã®äžè¬ç㪠ããŒãã€ã³ã = space oïŒ - åæ³šé ããã¢ããïŒ
QrCode::with_bitsã¡ãœããã«ã¯è¯ãäŸãããªããããŸãïŒ
gn gen ... --export-rust-project ã¯ãBUILD.gn ãã¡ã€ã«ãç·šéããåŸã«åå®è¡ããå¿
èŠãããããšïŒãã®ã»ãã·ã§ã³ã®æŒç¿å
šäœãéããŠäœåºŠãããããŸãïŒãææããŠãããšãããããããŸããã
ãã«ãã«ãŒã«æŒç¿
Chromium ã®ãã«ãã§ã//ui/base/BUILD.gn ã«æ°ãã Rust ã¿ãŒã²ããã远å ãã以äžãå«ããŠãã ããã
#![allow(unused)] fn main() { // Copyright 2023 Google LLC // SPDX-License-Identifier: Apache-2.0 // SAFETY: ãã®ååã®ä»ã®ã°ããŒãã«é¢æ°ã¯ãããŸããã #[unsafe(no_mangle)] pub extern "C" fn hello_from_rust() { println!("Hello from Rust!") } }
éèŠ: ããã§ã® no_mangle 㯠Rust ã³ã³ãã€ã©ã«ãã£ãŠäžçš®ã® unsafe ãšèŠãªããããããgn ã¿ãŒã²ããã§ unsafe ã³ãŒããèš±å¯ããå¿
èŠããããŸãã
ãã®æ°ãã Rust ã¿ãŒã²ããã //ui/base:base ã®äŸåé¢ä¿ãšããŠè¿œå ããŠãã ããããã®é¢æ°ã ui/base/resource/resource_bundle.cc ã®å
é ã§å®£èšããŠãã ããïŒåŸã§ãããããã€ã³ãã£ã³ã°çæããŒã«ã§èªååããæ¹æ³ãèŠãŠãããŸãïŒã
extern "C" void hello_from_rust();
ãã®é¢æ°ã ui/base/resource/resource_bundle.cc å
ã®ã©ããããåŒã³åºããŠãã ãããResourceBundle::MaybeMangleLocalizedString ã®å
é ãããããã§ããChromium ããã«ãããŠå®è¡ããâHello from Rust!â ãäœåºŠãåºåãããããšã確èªããŠãã ããã
VSCode ã䜿ã£ãŠããå Žåã¯ããã®ã¿ã€ãã³ã°ã§ VSCode ã§ Rust ãããŸãåäœããããã«èšå®ããŠãã ãããããã¯ä»¥éã®æŒç¿ã§åœ¹ç«ã¡ãŸããæåããŠããã°ãprintln! ã«å¯ŸããŠå³ã¯ãªãã¯ã®ãGo to definitionãã䜿ããããã«ãªããŸãã
åèæ å ±
rust_static_librarygn ãã³ãã¬ãŒã ã§å©çšã§ãããªãã·ã§ã³#[unsafe(no_mangle)]ã«é¢ããæ å ±extern "C"ã«é¢ããæ å ±- gn ã®
--export-rust-projectã¹ã€ããã«é¢ããæ å ± - VSCode ã§ rust-analyzer ãã€ã³ã¹ããŒã«ããæ¹æ³
ãã®äŸãå°ãçããã®ã¯ãæçµçã«æå°å ¬åæ¯ã®çžäºéçšèšèªã§ãã C ã«è¡ãçãããã§ããC++ ãš Rust ã¯ã©ã¡ãã C ABI 颿°ããã€ãã£ãã«å®£èšããŠåŒã³åºããŸããã³ãŒã¹ã®åŸåã§ã¯ãC++ ã Rust ã«çŽæ¥æ¥ç¶ããŸãã
allow_unsafe = true ãããã§å¿
èŠãªã®ã¯ã#[unsafe(no_mangle)] ã«ãã£ãŠ Rust ãåãååã®é¢æ°ã 2 ã€çæã§ããŠããŸãå¯èœæ§ããããRust ãã©ã¡ãã®é¢æ°ãæ£ããåŒã³åºãããããä¿èšŒã§ããªããªãããã§ãã
çŽç²ãª Rust ã®å®è¡ãã¡ã€ã«ãå¿
èŠãªå Žåã¯ãrust_executable gn ãã³ãã¬ãŒãã䜿ã£ãŠãããè¡ãããšãã§ããŸãã
ãã¹ã
Rust ã³ãã¥ããã£ã§ã¯éåžžããŠããããã¹ãã¯ãã¹ã察象ã®ã³ãŒããšåã ãœãŒã¹ãã¡ã€ã«å ã«çœ®ãããã¢ãžã¥ãŒã«ãšããŠèšè¿°ããŸããããã¯ã³ãŒã¹ã® ååã§èª¬æãããšããã§ã次ã®ããã«ãªããŸã:
#![allow(unused)] fn main() { // Copyright 2023 Google LLC // SPDX-License-Identifier: Apache-2.0 #[cfg(test)] mod tests { #[test] fn my_test() { todo!() } } }
Chromium ã§ã¯ããŠããããã¹ããå¥ã®ãœãŒã¹ãã¡ã€ã«ã«é
眮ããŠãããRust ã§ããã® æ
£è¡ãåŒãç¶ãæ¡çšããŸã â ããã«ãããã¹ããäžè²«ããŠèŠã€ãããããªãã .rs ãã¡ã€ã«ã 2 åç®ã«åãã«ãããããšïŒtest æ§æã§ïŒãé¿ããã®ã«åœ¹ç«ã¡ãŸãã
ãã®çµæãChromium ã§ Rust ã³ãŒãããã¹ãããæ¹æ³ãšããŠã次ã®éžæè¢ã ãããŸã:
- ãã€ãã£ã㪠Rust ãã¹ãïŒã€ãŸã
#[test]ïŒã//third_party/rustã®å€ã§ã¯æšå¥šãããŸããã - C++ ã§èšè¿°ããFFI åŒã³åºããä»ã㊠Rust ããã¹ããã
gtestãã¹ããRust ã³ãŒããåãªãèã FFI ã¬ã€ã€ãŒã§ãããæ¢åã®ãŠããããã¹ãã ãã®æ©èœãååã«ã«ããŒããŠããå Žåã«ã¯ãããã§ååã§ãã - Rust ã§èšè¿°ãããã¹ã察象ã®ã¯ã¬ãŒãããã®å
¬é API çµç±ã§äœ¿çšãã
gtestãã¹ãïŒå¿ èŠã«å¿ããŠpub mod for_testing { ... }ã䜿çšïŒããããæ¬¡ã®æ°æã®ã¹ã©ã€ãã®ããŒãã§ãã
ãµãŒãããŒãã£è£œã¯ã¬ãŒãã®ãã€ãã£ã㪠Rust ãã¹ãã¯ãæçµçã«ã¯ Chromium ãããã§å®è¡ãããã¹ãã§ããããšã«èšåããŠãã ãããïŒãã®çš®ã® ãã¹ããå¿ èŠã«ãªãã®ã¯ãŸãã§ããµãŒãããŒãã£è£œã¯ã¬ãŒãã远å ãŸãã¯æŽæ°ãã åŸã ãã§ããïŒ
C++ gtest ãš Rust gtest ã®ã©ã¡ãã䜿ãã¹ããã瀺ãã«ã¯ãããã€ãã® äŸã圹ç«ã€ãããããŸãã:
-
QR ã¯ãã¡ãŒã¹ãããŒãã£ã® Rust ã¬ã€ã€ãŒã«ã»ãšãã©æ©èœããªãïŒåãªã èã FFI ã°ã«ãŒã«ãããŸããïŒããã®ããæ¢åã® C++ ãŠããããã¹ãã䜿ã£ãŠ C++ å®è£ ãš Rust å®è£ ã®äž¡æ¹ããã¹ãããŸãïŒãã¹ãããã©ã¡ãŒã¿åãã
ScopedFeatureListã䜿ã£ãŠ Rust ãæå¹åãŸãã¯ç¡å¹åã§ããããã« ããŸãïŒã -
ä»®æ³ç㪠/ äœæ¥äžã® PNG çµ±åã§ã¯ã
libpngã«ã¯ãããã®ã®pngã¯ã¬ãŒã ã«ã¯ãªããã¯ã»ã«å€æã®ã¡ã¢ãªå®å šãªå®è£ ãå¿ èŠã«ãªããããããŸãã - ããšãã° RGBA => BGRA ãã¬ã³ãè£æ£ã§ãããã®ãããªæ©èœã¯ãRust ã§èšè¿°ãã åå¥ã®ãã¹ãã®æ©æµãåããå¯èœæ§ããããŸãã
rust_gtest_interop ã©ã€ãã©ãª
rust_gtest_interop ã©ã€ãã©ãªã¯ã次ã®ããšãè¡ãæ¹æ³ãæäŸããŸãã
- Rust 颿°ã
gtestã®ãã¹ãã±ãŒã¹ãšããŠäœ¿çšããïŒ#[gtest(...)]屿§ã䜿çšïŒ expect_eq!ããã³åæ§ã®ãã¯ãã䜿çšããïŒassert_eq!ã«äŒŒãŠããŸããããããã¯ããã ã¢ãµãŒã·ã§ã³ã倱æããŠããã¹ããçµäºããŸããïŒã
äŸ:
// Copyright 2023 Google LLC
// SPDX-License-Identifier: Apache-2.0
use rust_gtest_interop::prelude::*;
#[gtest(MyRustTestSuite, MyAdditionTest)]
fn test_addition() {
expect_eq!(2 + 2, 4);
}
Rust ãã¹ãã® GN ã«ãŒã«
Rust ã® gtest ãã¹ãããã«ãããæãç°¡åãªæ¹æ³ã¯ããã§ã« C++ ã§äœæããããã¹ããå«ãã§ããæ¢åã®ãã¹ããã€ããªã«ãããã远å ããããšã§ããããšãã°æ¬¡ã®ãšããã§ãã
test("ui_base_unittests") {
...
sources += [ "my_rust_lib_unittest.rs" ]
deps += [ ":my_rust_lib" ]
}
Rust ãã¹ããå¥åã® static_library ã§äœæããæ¹æ³ãæ©èœããŸããããµããŒãã©ã€ãã©ãªãžã®äŸåé¢ä¿ãæåã§å®£èšããå¿
èŠããããŸãã
rust_static_library("my_rust_lib_unittests") {
testonly = true
is_gtest_unittests = true
crate_root = "my_rust_lib_unittest.rs"
sources = [ "my_rust_lib_unittest.rs" ]
deps = [
":my_rust_lib",
"//testing/rust_gtest_interop",
]
}
test("ui_base_unittests") {
...
deps += [ ":my_rust_lib_unittests" ]
}
chromium::import! ãã¯ã
GN ã® deps ã« :my_rust_lib ã远å ããåŸããmy_rust_lib_unittest.rs ãã my_rust_lib ãã€ã³ããŒãããŠäœ¿çšããæ¹æ³ãçè§£ããå¿
èŠããããŸããmy_rust_lib ã«ã¯æç€ºç㪠crate_name ãæå®ããŠããªãããããã® crate åã¯å®å
šãªã¿ãŒã²ãããã¹ãšååã«åºã¥ããŠèšç®ãããŸãã幞ããèªåçã«ã€ã³ããŒãããã chromium crate ã® chromium::import! ãã¯ãã䜿ãã°ããã®ãããªæ±ãã«ããååãçŽæ¥æ±ããã«æžã¿ãŸãã
// Copyright 2023 Google LLC
// SPDX-License-Identifier: Apache-2.0
chromium::import! {
"//ui/base:my_rust_lib";
}
use my_rust_lib::my_function_under_test;
å éšçã«ã¯ããã®ãã¯ãã¯æ¬¡ã®ãããªãã®ã«å±éãããŸãã
// Copyright 2023 Google LLC
// SPDX-License-Identifier: Apache-2.0
extern crate ui_sbase_cmy_urust_ulib as my_rust_lib;
use my_rust_lib::my_function_under_test;
ããã«è©³ããæ
å ±ã¯ãchromium::import ãã¯ãã®ããã¥ã¡ã³ãã³ã¡ã³ãã«ãããŸãã
rust_static_library ã§ã¯ crate_name ããããã£ã䜿ã£ãŠæç€ºçãªååãæå®ã§ããŸããããããè¡ãããšã¯æšå¥šãããŸãããããã¯ãcrate åãã°ããŒãã«ã«äžæã§ãªããã°ãªããªãããã§ããcrates.io 㯠crate åã®äžææ§ãä¿èšŒããŠãããããcargo_crate GN ã¿ãŒã²ããïŒåŸã®ã»ã¯ã·ã§ã³ã§æ±ã gnrt ããŒã«ã«ãã£ãŠçæãããŸãïŒã§ã¯çã crate åã䜿ãããŸãã
ãã¹ãã®æŒç¿
å¥ã®æŒç¿ã®æéã§ãïŒ
Chromium ã®ãã«ãã§ã次ãè¡ã£ãŠãã ããã
hello_from_rustã®é£ã«ããã¹ãå¯èœãªé¢æ°ã远å ããŠãã ãããäŸ: åŒæ°ãšããŠåãåã£ã 2 ã€ã®æŽæ°ãå ç®ãããn çªç®ã®ãã£ããããæ°ãèšç®ãããã¹ã©ã€ã¹å ã®æŽæ°ãåèšããããªã©ã- æ°ãã颿°çšã®ãã¹ããå«ããå¥åã®
..._unittest.rsãã¡ã€ã«ã远å ããŠãã ããã - æ°ãããã¹ãã
BUILD.gnã«è¿œå ããŠãã ããã - ãã¹ãããã«ãããŠå®è¡ããæ°ãããã¹ããæ£ããåäœããããšã確èªããŠãã ããã
C++ ãšã®çžäºéçš
Rust ã³ãã¥ããã£ã§ã¯ãC++/Rust ã®çžäºéçšã®ããã«è€æ°ã®éžæè¢ãæäŸãããŠãããæ°ããããŒã«ãåžžã« éçºãããŠããŸããçŸæç¹ã§ Chromium ã§ã¯ãCXX ãšããããŒã«ã䜿çšããŠããŸãã
ã€ã³ã¿ãŒãã§ãŒã¹å®çŸ©èšèª ïŒRust ã«éåžžã«ãã䌌ãŠããŸãïŒã§èšèªå¢çå šäœãèšè¿°ãããšããã®åŸ CXX ããŒã«ã Rust ãš C++ ã®äž¡æ¹ã®é¢æ°ãšåã®å®£èšãçæããŸãã
ããã®äœ¿ç𿹿³ã®å®å šãªäŸã«ã€ããŠã¯ãCXX ãã¥ãŒããªã¢ã«ãåç §ããŠãã ããã
å³ã«æ²¿ã£ãŠèª¬æããŠãã ãããå éšã§ã¯ãããã¯åã«è¡ã£ãããšãšãŸã£ããåãããšã ããŠãããšèª¬æããŠãã ãããããã«ããã®ããã»ã¹ãèªååããããšã«ã¯æ¬¡ã®å©ç¹ã ããããšãææããŠãã ãã:
- ãã®ããŒã«ã¯ãC++ åŽãš Rust åŽãäžèŽããããšãä¿èšŒããŸãïŒããšãã°
#[cxx::bridge]ãå®éã® C++ ãŸã㯠Rust ã®å®çŸ©ãšäžèŽããªãå Žåã¯ã³ã³ãã€ã« ãšã©ãŒã«ãªããŸãããåæããŠããªãæåãã€ã³ãã£ã³ã°ã§ã¯æªå®çŸ©åäœãçºçããŸãïŒ - ãã®ããŒã«ã¯ãC 以å€ã®æ©èœã«å¯Ÿãã FFI ãµã³ã¯ïŒå°ãããC ABI äºæã® ãããã¬ãã«é¢æ°ïŒã®çæãèªååããŸãïŒããšãã° Rust ãŸã㯠C++ ã® ã¡ãœãããžã® FFI åŒã³åºããå¯èœã«ããŸããæåãã€ã³ãã£ã³ã°ã§ã¯ããã®ãã㪠ãããã¬ãã«é¢æ°ãæäœæ¥ã§äœæããå¿ èŠããããŸãïŒ
- ãã®ããŒã«ãšã©ã€ãã©ãªã¯ãäžé£ã®äžæ žãšãªãåãæ±ããŸããããšãã°:
&[T]ã¯ãç¹å®ã® ABI ãã¡ã¢ãªã¬ã€ã¢ãŠããä¿èšŒããªãã«ããããããã FFI å¢çãè¶ããŠæž¡ããŸããæåãã€ã³ãã£ã³ã°ã§ã¯std::span<T>/&[T]ã æäœæ¥ã§åè§£ãããã€ã³ã¿ãšé·ãããåæ§ç¯ããå¿ èŠããããŸããåèšèªã§ 空ã®ã¹ã©ã€ã¹ã®è¡šçŸããããã«ç°ãªããããããã¯ãšã©ãŒãèµ·ãããããã§ã)std::unique_ptr<T>ãstd::shared_ptr<T>ãããã³/ãŸãã¯Boxã®ãã㪠ã¹ããŒããã€ã³ã¿ã¯ãã€ãã£ãã«ãµããŒããããŠããŸããæåãã€ã³ãã£ã³ã°ã§ã¯ã C ABI äºæã®çãã€ã³ã¿ãæž¡ããªããã°ãªããã寿åœç®¡çãš ã¡ã¢ãªå®å šæ§ã®ãªã¹ã¯ãé«ãŸããŸããrust::StringãšCxxStringåã¯ãèšèªéã«ãããæåå衚çŸã®éããçè§£ãã ãããä¿ã£ããŸãŸæ±ããŸãïŒããšãã°ãrust::String::lossy㯠UTF-8 ã§ã¯ãªã å ¥åãã Rust ã®æååãæ§ç¯ã§ããrust::String::c_strã¯æååã NUL çµç«¯ã§ããŸãïŒã
ãã€ã³ãã£ã³ã°ã®äŸ
CXX ã§ã¯ãC++/Rust å¢çå
šäœãã.rs ãœãŒã¹ã³ãŒãå
ã® cxx::bridge ã¢ãžã¥ãŒã«ã§å®£èšããå¿
èŠããããŸãã
// èäœæš© 2023 Google LLC
// SPDX-License-Identifier: Apache-2.0
#[cxx::bridge]
mod ffi {
extern "Rust" {
type MultiBuf;
fn next_chunk(buf: &mut MultiBuf) -> &[u8];
}
unsafe extern "C++" {
include!("example/include/blobstore.h");
type BlobstoreClient;
fn new_blobstore_client() -> UniquePtr<BlobstoreClient>;
fn put(self: &BlobstoreClient, buf: &mut MultiBuf) -> Result<u64>;
}
}
// Definitions of Rust types and functions go here
泚ç®ç¹:
- ããã¯éåžžã® Rust ã®
modã®ããã«èŠããŸããã#[cxx::bridge]ããã·ãŒãžã£ã«ãã¯ãã¯ããã«å¯ŸããŠè€éãªåŠçãè¡ããŸããçæãããã³ãŒãã¯ããªãé«åºŠã§ãããããã§ãæçµçã«ã¯ãã³ãŒãå ã«ffiãšããååã®modãäœãããŸãã - Rust ã§ã® C++ ã®
std::unique_ptrã®ãã€ãã£ããµããŒã - C++ ã§ã® Rust ã¹ã©ã€ã¹ã®ãã€ãã£ããµããŒã
- ïŒäžéšïŒC++ ãã Rust ãžã®åŒã³åºããš Rust ã®å
- ïŒäžéšïŒRust ãã C++ ãžã®åŒã³åºããš C++ ã®å
ãããã誀解: Rust ã C++ ããããŒãè§£æããŠãã ããã«èŠããŸã ããããã¯èª€è§£ãæããŸãããã®ããããŒã¯ Rust ã«ãã£ãŠè§£éãããããšã¯ãªããåã«çæããã C++ ã³ãŒãã®äžã§ C++ ã³ã³ãã€ã©ã®ããã« #include ãããã ãã§ãã
CXX ã®å¶éäºé
CXX ã䜿çšããéã«å§åçã«æã圹ç«ã€ããŒãžã¯ãåãªãã¡ã¬ã³ã¹ ã§ãã
CXX ãæ¬è³ªçã«é©ããŠããã®ã¯ã次ã®ãããªã±ãŒã¹ã§ãã
- Rust-C++ ã€ã³ã¿ãŒãã§ãŒã¹ãååã«åçŽã§ããã®ãã¹ãŠã宣èšã§ããå Žåã
- CXX ããã§ã«ãã€ãã£ãã«ãµããŒãããŠããåã ãã䜿ã£ãŠããå Žåãããšãã°
std::unique_ptrãstd::stringã&[u8]ãªã©ã§ãã
ããã«ã¯å€ãã®å¶éããããŸããããšãã°ãRust ã® Option åããµããŒããããŠããŸããã
ãããã®å¶éã«ãããChromium ã§ã¯ Rust ãä»»æã® Rust-C++ çžäºéçšã®ãã ã«äœ¿ãã®ã§ã¯ãªããååã«åé¢ããã ããªãŒãããŒããã«å¯ŸããŠã®ã¿äœ¿çšããããšã«ãªããŸããChromium ã§ Rust ã® ãŠãŒã¹ã±ãŒã¹ãæ€èšããéã®ããåºçºç¹ã¯ãèšèªå¢çã«å¯Ÿãã CXX ãã€ã³ãã£ã³ã°ãäžæžããããããååã«åçŽã«èŠãããã©ããã確ãããããš ã§ãã
ãŸããCXX ã«é¢ããä»ã®åä»ãªç¹ã«ã€ããŠãè°è«ãã¹ãã§ããããšãã°:
- ãã®ãšã©ãŒãã³ããªã³ã°ã¯ C++ äŸå€ã«åºã¥ããŠããŸãïŒæ¬¡ã®ã¹ã©ã€ãã§èª¬æããŸãïŒ
- 颿°ãã€ã³ã¿ã¯æ±ãã¥ããã§ãã
CXX ã®ãšã©ãŒãã³ããªã³ã°
CXX ã® Result<T,E> ã®ãµããŒã 㯠C++ äŸå€ã«äŸåããŠãããããChromium ã§ã¯ããã䜿çšã§ããŸãããä»£æ¿æ¡ã¯æ¬¡ã®ãšããã§ãã
-
Result<T, E>ã®Tã®éšåã¯ã次ã®ããã«ã§ããŸãã- åºåãã©ã¡ãŒã¿çµç±ã§è¿ãïŒäŸ:
&mut Tçµç±ïŒãããã«ã¯ãTã FFI å¢çãè¶ããŠæž¡ããããšãå¿ èŠã§ããããšãã°ãTã¯æ¬¡ã®ããããã§ããå¿ èŠããããŸãã- ããªããã£ãåïŒ
u32ãusizeãªã©ïŒ cxxããã€ãã£ãã«ãµããŒãããåïŒUniquePtr<T>ãªã©ïŒã§ã倱ææã«äœ¿çšã§ããé©åãªããã©ã«ãå€ãæã€ãã®ïŒBox<T>ãšã¯ ç°ãªãïŒ
- ããªããã£ãåïŒ
- Rust åŽã«ä¿æããåç
§çµç±ã§å
¬éãããããã¯ã
Tã Rust ã®åã§ãFFI å¢çãè¶ããŠæž¡ãããUniquePtr<T>ã«æ ŒçŽããããšãã§ããªãå Žåã«å¿ èŠã«ãªãããšããããŸãã
- åºåãã©ã¡ãŒã¿çµç±ã§è¿ãïŒäŸ:
-
Result<T, E>ã®Eã®éšåã¯ã次ã®ããã«ã§ããŸãã- çåœå€ãšããŠè¿ãïŒäŸ:
trueã¯æåã衚ããfalseã¯å€±æã衚ãïŒ - ãšã©ãŒã®è©³çްãä¿æããããšã¯çè«äžå¯èœã§ããããããŸã§ã®ãšããå®éã«ã¯å¿ èŠã«ãªã£ãŠããŸããã
- çåœå€ãšããŠè¿ãïŒäŸ:
CXX ãšã©ãŒãã³ããªã³ã°: QR ã®äŸ
QR ã³ãŒããžã§ãã¬ãŒã¿ãŒã¯ãæåãšå€±æã®äŒéã« boolean ã䜿ããã æåããçµæã FFI å¢çããŸããã§æž¡ããäŸã§ãã
// Copyright 2023 Google LLC
// SPDX-License-Identifier: Apache-2.0
#[cxx::bridge(namespace = "qr_code_generator")]
mod ffi {
extern "Rust" {
fn generate_qr_code_using_rust(
data: &[u8],
min_version: i16,
out_pixels: Pin<&mut CxxVector<u8>>,
out_qr_size: &mut usize,
) -> bool;
}
}
åè¬è
ã¯ãout_qr_size åºåã®æå³ãæ°ã«ãªããããããŸããããã㯠ãã¯ã¿ãŒã®ãµã€ãºã§ã¯ãªããQR ã³ãŒãã®ãµã€ãºã§ãïŒãããŠç¢ºãã«å°ãåé·ã§ã ããã¯ãã¯ã¿ãŒã®ãµã€ãºã®å¹³æ¹æ ¹ã§ãïŒã
Rust 颿°ãåŒã³åºãåã« out_qr_size ãåæåããããšã®éèŠæ§ãææãã 䟡å€ããããããããŸãããæªåæåã¡ã¢ãªãæã Rust ã®åç
§ãäœæãããšã æªå®çŸ©åäœã«ãªããŸãïŒC++ ãšã¯ç°ãªããC++ ã§ã¯ãã®ãããªã¡ã¢ãªã ããªãã¡ã¬ã³ã¹ãããšãã«ã®ã¿ UB ã«ãªããŸãïŒã
åè¬è
ã Pin ã«ã€ããŠè³ªåããå Žåã¯ãCXX ã C++ ããŒã¿ãžã®å¯å€åç
§ã« ãããå¿
èŠãšããçç±ã説æããŠãã ãããçãã¯ãC++ ããŒã¿ã«ã¯èªå·±åç
§ ãã€ã³ã¿ãŒãå«ãŸããŠããå¯èœæ§ããããããRust ããŒã¿ã®ããã«ç§»åã§ããªã ããã§ãã
CXX ãšã©ãŒãã³ããªã³ã°: PNG ã®äŸ
PNG ãã³ãŒããŒã®ãããã¿ã€ãã¯ãæåçµæã FFI å¢çãè¶ããŠæž¡ããªãå Žåã«äœãã§ãããã瀺ããŠããŸãã
// Copyright 2023 Google LLC
// SPDX-License-Identifier: Apache-2.0
#[cxx::bridge(namespace = "gfx::rust_bindings")]
mod ffi {
extern "Rust" {
/// ãã㯠`Result<PngReader<'a>,
/// ()>` ãš FFI ãã¬ã³ããªãŒã«ç䟡ãªãã®ãè¿ããŸãã
fn new_png_reader<'a>(input: &'a [u8]) -> Box<ResultOfPngReader<'a>>;
/// `crate::png::ResultOfPngReader` åã®ããã® C++ ãã€ã³ãã£ã³ã°ã
type ResultOfPngReader<'a>;
fn is_err(self: &ResultOfPngReader) -> bool;
fn unwrap_as_mut<'a, 'b>(
self: &'b mut ResultOfPngReader<'a>,
) -> &'b mut PngReader<'a>;
/// `crate::png::PngReader` åã®ããã® C++ ãã€ã³ãã£ã³ã°ã
type PngReader<'a>;
fn height(self: &PngReader) -> u32;
fn width(self: &PngReader) -> u32;
fn read_rgba8(self: &mut PngReader, output: &mut [u8]) -> bool;
}
}
PngReader ãš ResultOfPngReader 㯠Rust ã®åã§ãããããã®åã®ãªããžã§ã¯ãã¯ãBox<T> ã«ãã鿥åãªãã§ã¯ FFI å¢çãè¶ããããšãã§ããŸãããout_parameter: &mut PngReader ã䜿ãããšã¯ã§ããŸããããªããªããCXX ã§ã¯ C++ ã Rust ãªããžã§ã¯ããå€ãšããŠä¿æããããšãèš±å¯ãããŠããªãããã§ãã
ãã®äŸã¯ãCXX ãä»»æã®ãžã§ããªã¯ã¹ããã³ãã¬ãŒãããµããŒãããŠããªããŠããããããéãžã§ããªãã¯åã«æåã§ç¹æ®å / ã¢ãã¢ãŒãã£ãã¯åããããšã§ãFFI å¢çãè¶ããŠæž¡ããããšã瀺ããŠããŸãããã®äŸã§ã¯ãResultOfPngReader ã¯éãžã§ããªãã¯åã§ãããResult<T, E> ã®é©åãªã¡ãœããïŒããšãã° is_errãunwrapãããã³/ãŸã㯠as_mutïŒã«åŠçã転éããŸãã
Chromium ã§ cxx ã䜿ã
Chromium ã§ã¯ãRust ã䜿ãããåãªãŒãããŒãããšã«ãç¬ç«ãã #[cxx::bridge] mod ãå®çŸ©ããŸããéåžžã¯ãrust_static_library ããšã« 1 ã€çšæããŸããæ¬¡ã远å ããŸãã
cxx_bindings = [ "my_rust_file.rs" ]
# #[cxx::bridge] ãå«ããã¡ã€ã«ã®äžèЧã§ããããã¹ãŠã®ãœãŒã¹ãã¡ã€ã«ã§ã¯ãããŸãã
allow_unsafe = true
ãããæ¢åã® rust_static_library ã¿ãŒã²ããã® crate_root ããã³ sources ãšäžŠã¹ãŠè¿œå ããŸãã
C++ ããããŒã¯é©åãªå Žæã«çæãããã®ã§ãåã«æ¬¡ã®ããã«ã§ããŸãã
#include "ui/base/my_rust_file.rs.h"
Chromium ã® C++ åãš CXX ã® Rust åãçžäºã«å€æããããã®ãŠãŒãã£ãªãã£é¢æ°ã //base ã«ããã€ããããŸããããšãã° SpanToRustSlice ã§ãã
åè¬è
ããã¯æ¬¡ã®ãããªè³ªåããããããããŸãã â ããã§ããªã allow_unsafe = true ãå¿
èŠãªã®ã¯ãªãã§ããããïŒ
倧ãŸããªçãã¯ãéåžžã® Rust ã®åºæºã§ã¯ãã©ã® C/C++ ã³ãŒãããå®å
šãã§ã¯ãªããšããããšã§ãã Rust ãã C/C++ ãè¡ãæ¥ããªããåŒã³åºããšãã¡ã¢ãªã«å¯ŸããŠä»»æã®ããšãè¡ãå¯èœæ§ãããã Rust èªèº«ã®ããŒã¿ã¬ã€ã¢ãŠãã®å®å
šæ§ãæãªããããããããŸããC/C++ çžäºéçšã«ãã㊠å€ããã unsafe ããŒã¯ãŒããååšãããšããã®ãããªããŒã¯ãŒãã®ã·ã°ãã«å¯Ÿãã€ãºæ¯ãæãªãå¯èœæ§ãããã ãã㯠è°è«ã®ããç¹ ã§ãããå³å¯ã«èšãã°ãRust ãã€ããªã«å€éšã³ãŒããåã蟌ãããšèªäœãã Rust ã®èгç¹ããã¯äºæããªãåäœãåŒãèµ·ããåŸãŸãã
ç矩ã®çã㯠ãã®ããŒãž ã®å
é ã«ããå³ã«ãããŸã â å
éšã§ã¯ã CXX ã¯åã®ã»ã¯ã·ã§ã³ã§æäœæ¥ã§è¡ã£ãã®ãšåãããã«ãRust ã® unsafe ã〠extern "C" ãªé¢æ°ãçæããŸãã
æŒç¿: C++ ãšã®çžäºéçš
ããŒã 1
- 以åäœæãã Rust ãã¡ã€ã«ã«
#[cxx::bridge]ã远å ããC++ ããåŒã³åºãããåäžã®é¢æ°hello_from_rustãæå®ããŠãã ããããã®é¢æ°ã¯åŒæ°ãåãããæ»ãå€ããããŸããã - 以åã®
hello_from_rust颿°ãä¿®æ£ããextern "C"ãš#[unsafe(no_mangle)]ãåé€ããŠãã ãããããã¯åãªãæšæºç㪠Rust 颿°ã«ãªããŸãã - ãããã®ãã€ã³ãã£ã³ã°ããã«ãããããã«
gnã¿ãŒã²ãããä¿®æ£ããŠãã ããã - C++ ã³ãŒãã§ã¯ã
hello_from_rustã®åæ¹å®£èšãåé€ããŠãã ããã代ããã«ãçæãããããããŒãã¡ã€ã«ãã€ã³ã¯ã«ãŒãããŠãã ããã - ãã«ãããŠå®è¡ããŸãããïŒ
ããŒã 2
å°ã CXX ã詊ããŠã¿ããšããã§ããããããããããšã§ãChromium ã«ããã Rust ãå®éã«ã¯ã©ãã»ã©æè»ããèããå©ãã«ãªããŸãã
詊ããŠã¿ãããš:
- Rust ãã C++ ã«ã³ãŒã«ããã¯ãããå¿
èŠã«ãªããã®ã¯æ¬¡ã®ãšããã§ã:
cxx::bridgeããinclude!ã§ãã远å ã®ããããŒãã¡ã€ã«ã ãã®æ°ããããããŒãã¡ã€ã«å ã§ C++ 颿°ã宣èšããå¿ èŠããããŸãã- ãã®ãããªé¢æ°ãåŒã³åºãããã®
unsafeãããã¯ãããã㯠ããã§èª¬æãããŠãã ããã«#[cxx::bridge]ã§unsafeããŒã¯ãŒããæå®ããããšã - ãŸãã
#include "third_party/rust/cxx/v1/crate/include/cxx.h"ãå¿ èŠã«ãªãå ŽåããããŸã
- C++ æååã C++ ãã Rust ã«æž¡ãã
- C++ ãªããžã§ã¯ããžã®åç §ã Rust ã«æž¡ãã
- æå³çã« Rust 颿°ã®ã·ã°ããã£ã
#[cxx::bridge]ãšäžèŽããªãããã«ããŠã衚瀺ããããšã©ãŒã«æ £ããã - æå³çã« C++ 颿°ã®ã·ã°ããã£ã
#[cxx::bridge]ãšäžèŽããªãããã«ããŠã衚瀺ããããšã©ãŒã«æ £ããã - äœããã®åã®
std::unique_ptrã C++ ãã Rust ã«æž¡ããŠãRust ã C++ ãªããžã§ã¯ããææã§ããããã«ããã - Rust ãªããžã§ã¯ããäœæã㊠C++ ã«æž¡ããC++ ããããææããããã«ãããïŒãã³ã:
Boxãå¿ èŠã§ããïŒ - C++ åã«ããã€ãã®ã¡ãœããã宣èšãããããã Rust ããåŒã³åºãã
- Rust åã«ããã€ãã®ã¡ãœããã宣èšãããããã C++ ããåŒã³åºãã
ããŒã 3
ããã§ CXX çžäºéçšã®åŒ·ã¿ãšå¶çŽãããã£ãã®ã§ãã€ã³ã¿ãŒãã§ãŒã¹ãååã«ã·ã³ãã«ã«ãªã Chromium ã«ããã Rust ã®ãŠãŒã¹ã±ãŒã¹ã 2 ã€ã»ã©èããŠã¿ãŠãã ããããã®ã€ã³ã¿ãŒãã§ãŒã¹ãã©ã®ããã«å®çŸ©ããããæŠç¥ã瀺ããŠãã ããã
åèè³æ
ããªããééããããªè³ªåã®äžéšã以äžã«ç€ºããŸã:
- X ãš Y ã®äž¡æ¹ã颿°åã§ããã«ãããããããå Y ã§å X ã®å€æ°ãåæåããããšããŠåé¡ãçºçããŠããŸããããã¯ãC++ 颿°ã
cxx::bridgeå ã®å®£èšãšå®å šã«ã¯äžèŽããŠããªãããã§ãã - C++ ã®åç §ã Rust ã®åç §ã«èªç±ã«å€æã§ããããã«èŠããŸãããã㯠UB ã®å±éºã¯ãªãã®ã§ãããããCXX ã® opaque åã«ã€ããŠã¯ããŒããµã€ãºãªã®ã§å±éºã¯ãããŸãããCXX ã® trivial åã«ã€ããŠã¯ãã¯ããUB ãåŒãèµ·ããããšã¯ å¯èœ ã§ãããã ããCXX ã®èšèšäžããã®ãããªäŸãäœãã®ã¯ããªãå°é£ã§ãã
ãµãŒãããŒã㣠ã¯ã¬ãŒãã®è¿œå
Rust ã®ã©ã€ãã©ãªã¯ãã¯ã¬ãŒãããšåŒã°ããcrates.io ã«ãããŸããRust ã¯ã¬ãŒãå士ãäºãã«äŸåããã®ã¯ éåžžã«ç°¡å ã§ããã§ãããå®éã«ãããªã£ãŠããŸãïŒ
| é ç® | C++ ã©ã€ãã©ãª | Rust ã¯ã¬ãŒã |
|---|---|---|
| ãã«ãã·ã¹ãã | ããŸã㟠| äžè²«ããŠãã: Cargo.toml |
| äžè¬çãªã©ã€ãã©ãªã®èŠæš¡ | ãã倧ãã | å°ãã |
| æšç§»çäŸåé¢ä¿ | å°ãªã | å€ã |
Chromium ãšã³ãžãã¢ã«ãšã£ãŠãããã«ã¯é·æãšçæããããŸã:
- ãã¹ãŠã®ã¯ã¬ãŒããå ±éã®ãã«ãã·ã¹ãã ã䜿ã£ãŠããããããããã® Chromium ãžã®åã蟌ã¿ãèªååã§ããŸãâŠ
- ⊠ãã ããã¯ã¬ãŒãã«ã¯éåžžãæšç§»çäŸåé¢ä¿ããããããè€æ°ã® ã©ã€ãã©ãªãåã蟌ãå¿ èŠãçããå¯èœæ§ããããŸãã
以äžã説æããŸã:
- ã¯ã¬ãŒãã Chromium ã®ãœãŒã¹ã³ãŒãããªãŒã«é 眮ããæ¹æ³
- ãã®ããã®
gnãã«ãã«ãŒã«ãäœæããæ¹æ³ - ãœãŒã¹ã³ãŒããç£æ»ããŠååãªå®å šæ§ã確èªããæ¹æ³
ã¯ã¬ãŒãã远å ããããã® Cargo.toml ãã¡ã€ã«ã®èšå®
Chromium ã«ã¯ãäžå
管çãããçŽæ¥ã®ã¯ã¬ãŒãäŸåé¢ä¿ã®ã»ããã 1 ã€ãããŸãããããã¯åäžã® Cargo.toml ãéããŠç®¡çãããŸãã
[dependencies]
bitflags = "1"
cfg-if = "1"
cxx = "1"
# ã»ãã«ã倿°...
ã»ãã® Cargo.toml ãšåæ§ã«ãäŸåé¢ä¿ã«ã€ããŠããã«è©³çŽ°ãªæ
å ± ãæå®ã§ããŸã â éåžžã¯ããã®ã¯ã¬ãŒãã§æå¹ã«ããã features ãæå®ããããšã«ãªããŸãã
Chromium ã«ã¯ã¬ãŒãã远å ããéã«ã¯ã远å ã®ãã¡ã€ã« gnrt_config.toml ã«è¿œå æ
å ±ãèšè¿°ããå¿
èŠãããããšããããããŸããããã«ã€ããŠã¯æ¬¡ã§èª¬æããŸãã
gnrt_config.toml ã®èšå®
Cargo.toml ãšäžŠãã§ gnrt_config.toml ããããŸããããã«ã¯ã crate ã®åãæ±ãã«å¯Ÿãã Chromium åºæã®æ¡åŒµãå«ãŸããŠããŸãã
æ°ãã crate ã远å ããå Žåã¯ãå°ãªããšã group ãæå®ãã¹ãã§ããããã¯æ¬¡ã®ããããã§ãã
# 'safe': ãã®ã©ã€ãã©ãªã¯ rule-of-2 ãæºãããŠãããã©ã®ããã»ã¹ã§ã䜿çšã§ããŸãã
# 'sandbox': ãã®ã©ã€ãã©ãªã¯ rule-of-2 ãæºãããŠãããã
# ã¬ã³ãã©ãŒããã»ã¹ããŠãŒãã£ãªãã£ããã»ã¹ãªã©ã®ãµã³ãããã¯ã¹åããã
# ããã»ã¹ã§äœ¿çšããªããã°ãªããŸããã
# 'test': ãã®ã©ã€ãã©ãªã¯ãã¹ãã§ã®ã¿äœ¿çšãããŸãã
ããšãã°ã
[crate.my-new-crate]
group = 'test' # ãã¹ãã³ãŒãã§ã®ã¿äœ¿çšããã
crate ã®ãœãŒã¹ã³ãŒãã®ã¬ã€ã¢ãŠãã«ãã£ãŠã¯ããã® LICENSE ãã¡ã€ã«ãã©ãã§ èŠã€ããããããæå®ããããã«ããã®ãã¡ã€ã«ã䜿çšããå¿
èŠãããå ŽåããããŸãã
åŸã§ãåé¡ã解決ããããã«ãã®ãã¡ã€ã«ã§èšå®ããå¿ èŠããããã®ä»ã®é ç®ãèŠãŠãããŸãã
ã¯ã¬ãŒãã®ããŠã³ããŒã
gnrt ãšããããŒã«ã¯ãã¯ã¬ãŒããããŠã³ããŒãããBUILD.gn ã«ãŒã«ãçæã§ããŸãã
ãŸããæ¬¡ã®ããã«ããŠå¿ èŠãªã¯ã¬ãŒããããŠã³ããŒãããŸãã
cd chromium/src
vpython3 tools/crates/run_gnrt.py -- vendor
gnrtããŒã«ã¯ Chromium ã®ãœãŒã¹ã³ãŒãã®äžéšã§ããããã® ã³ãã³ããå®è¡ãããšããã®äŸåé¢ä¿ãcrates.ioããããŠã³ããŒãããŠå®è¡ããããšã«ãªããŸãã ãã®ã»ãã¥ãªãã£äžã®å€æã«ã€ããŠã¯ãåã®ã»ã¯ã·ã§ã³ãåç §ããŠãã ããã
ãã® vendor ã³ãã³ãã§ã¯ã次ã®ãã®ãããŠã³ããŒããããå¯èœæ§ããããŸãã
- æå®ããã¯ã¬ãŒã
- çŽæ¥äŸåé¢ä¿ããã³æšç§»çäŸåé¢ä¿
cargoã Chromium ã«å¿ èŠãªã¯ã¬ãŒãäžåŒãå®å šã«è§£æ±ºããããã«å¿ èŠãªã ä»ã®ã¯ã¬ãŒãã®æ°ããããŒãžã§ã³
Chromium ã§ã¯ãäžéšã®ã¯ã¬ãŒãçšã®ãããã //third_party/rust/chromium_crates_io/patches ã«ä¿æããŠããŸãããããã¯èªåçã«åé©çš ãããŸããããããã®é©çšã«å€±æããå Žåã¯æåã§å¯Ÿå¿ããå¿
èŠããããããããŸããã
gn ãã«ãã«ãŒã«ã®çæ
ã¯ã¬ãŒããããŠã³ããŒãããããæ¬¡ã®ããã« BUILD.gn ãã¡ã€ã«ãçæããŸã:
vpython3 tools/crates/run_gnrt.py -- gen
次㫠git status ãå®è¡ããŸãã以äžãèŠã€ããã¯ãã§ã:
third_party/rust/chromium_crates_io/vendorã« å°ãªããšã 1 ã€ã®æ°ããã¯ã¬ãŒãã®ãœãŒã¹ã³ãŒãthird_party/rust/<crate name>/v<major semver version>ã« å°ãªããšã 1 ã€ã®æ°ããBUILD.gn- é©åãª
README.chromium
ãmajor semver versionããšã¯ãRust ã®ãsemverãããŒãžã§ã³çªå·ã®ããšã§ãã
ç¹ã« third_party/rust ã«çæããããã®ããã確èªããŠãã ããã
semver ã«ã€ããŠå°ã説æããŠãã ãã â ç¹ã«ãChromium ã§ã¯ããã 1 ã€ã®ã¯ã¬ãŒãã®äºææ§ã®ãªãè€æ°ããŒãžã§ã³ã蚱容ããããã®ãã®ã§ããç¹ã«ã€ããŠã§ããããã¯æšå¥šãããŸãããã Cargo ãšã³ã·ã¹ãã ã§ã¯å¿ èŠã«ãªãå ŽåããããŸãã
åé¡ã®è§£æ±º
ãã«ãã倱æããå Žåããã®åå 㯠build.rs ãããããŸãããããã¯ããã«ãæã«ä»»æã®åŠçãè¡ãããã°ã©ã ã§ããããã¯ããã«ãã®äžŠåæ§ãšåçŸæ§ãæå€§åããããã«éçã§æ±ºå®è«çãªãã«ãã«ãŒã«ãç®æã gn ãš ninja ã®èšèšãšæ ¹æ¬çã«çžå®¹ããŸããã
äžéšã® build.rs ã®åŠçã¯èªåçã«ãµããŒããããŸããããã以å€ã¯å¯Ÿå¿ãå¿
èŠã§ãã
| ãã«ãã¹ã¯ãªããã®å¹æ | ç§ãã¡ã® gn ãã³ãã¬ãŒãã§ãµããŒã | ããªãã«å¿ èŠãªäœæ¥ |
|---|---|---|
| æ©èœã®æå¹/ç¡å¹ãåãæ¿ããããã® rustc ããŒãžã§ã³ç¢ºèª | ã¯ã | ãªã |
| æ©èœã®æå¹/ç¡å¹ãåãæ¿ããããã®ãã©ãããã©ãŒã ãŸã㯠CPU ã®ç¢ºèª | ã¯ã | ãªã |
| ã³ãŒãçæ | ã¯ã | ã¯ã - gnrt_config.toml ã§æå® |
| C/C++ ã®ãã«ã | ããã | ãããåé¿ããããã«ããããåœãŠã |
| ãã®ä»ã®ä»»æã®åŠç | ããã | ãããåé¿ããããã«ããããåœãŠã |
幞ããªããšã«ãã»ãšãã©ã®ã¯ã¬ãŒãã«ã¯ãã«ãã¹ã¯ãªãããå«ãŸããŠãããããŸã幞ããªããšã«ãã»ãšãã©ã®ãã«ãã¹ã¯ãªããã¯äžã® 2 ã€ã®åŠçããè¡ããŸããã
ã³ãŒããçæãããã«ãã¹ã¯ãªãã
ninja ãäžè¶³ããŠãããã¡ã€ã«ã«ã€ããŠãšã©ãŒãåºãå Žåã¯ãbuild.rs ã確èªããŠãããã ãœãŒã¹ã³ãŒããã¡ã€ã«ãæžãåºããŠãããã©ããã確èªããŠãã ããã
ããã§ããã°ãgnrt_config.toml ã倿ŽããŠããã® ã¯ã¬ãŒãã« build-script-outputs ã远å ããŠãã ããããããæšç§»çäŸåé¢ä¿ã ã€ãŸã Chromium ã®ã³ãŒããçŽæ¥äŸåãã¹ãã§ã¯ãªããã®ã§ããå Žåã¯ã allow-first-party-usage=false ã远å ããŠãã ããããã®ãã¡ã€ã«ã«ã¯ããã§ã« ããã€ãã®äŸããããŸãã
[crate.unicode-linebreak]
allow-first-party-usage = false
build-script-outputs = ["tables.rs"]
次ã«ãgnrt.py -- gen ãåå®è¡ã㊠BUILD.gn ãã¡ã€ã«ãåçæãããã®ç¹å®ã® åºåãã¡ã€ã«ãåŸç¶ã®ãã«ãæé ãžã®å
¥åã§ããããšã ninja ã«ç¥ãããŠãã ããã
C++ ããã«ããããä»»æã®ã¢ã¯ã·ã§ã³ãå®è¡ããããããã«ãã¹ã¯ãªãã
äžéšã® crate ã¯ãC/C++ ã©ã€ãã©ãªããã«ãããŠãªã³ã¯ããããã« cc crate ã䜿çšããŸããã»ãã® crate ã¯ããã«ãã¹ã¯ãªããå
ã§ bindgen ã䜿çšã㊠C/C++ ãè§£æããŸãããããã®ã¢ã¯ã·ã§ã³ã¯ Chromium ã®ã³ã³ããã¹ãã§ã¯ãµããŒãã§ããŸãã â Chromium ã® gnãninjaãLLVM ãã«ãã·ã¹ãã ã§ã¯ããã«ãã¢ã¯ã·ã§ã³éã®é¢ä¿ã衚çŸããæ¹æ³ãéåžžã«å³å¯ã«å®ããããŠããããã§ãã
ãããã£ãŠãéžæè¢ã¯æ¬¡ã®ãšããã§ãã
- ãããã® crate ãé¿ãã
- crate ã«ããããé©çšãã
ããã㯠third_party/rust/chromium_crates_io/patches/<crate> ã«çœ®ãå¿
èŠããããŸããäŸãšã㊠cxx crate ã«å¯Ÿããããã ãåç
§ããŠãã ããããããã®ãããã¯ãgnrt ã crate ãã¢ããã°ã¬ãŒããããã³ã«èªåçã«é©çšãããŸãã
Crate ãžã®äŸå
ãµãŒãããŒãã£ã® crate ã远å ããŠãã«ãã«ãŒã«ãçæããããcrate ãžã®äŸåã¯ç°¡åã§ããrust_static_library ã¿ãŒã²ãããèŠã€ããŠããã® crate å
ã® :lib ã¿ãŒã²ãããžã® dep ã远å ããŸãã
å ·äœçã«ã¯ã次ã®ãšããã§ãã
ããšãã°ã次ã®ããã«ãªããŸãã
rust_static_library("my_rust_lib") {
crate_root = "lib.rs"
sources = [ "lib.rs" ]
deps = [ "//third_party/rust/example_rust_crate/v1:lib" ]
}
ãµãŒãããŒãã£ã®ã¯ã¬ãŒãã®ç£æ»
æ°ããã©ã€ãã©ãªã®è¿œå 㯠Chromium ã®æšæºããªã·ãŒã«åŸããŸããããã¡ããã»ãã¥ãªãã£ã¬ãã¥ãŒã®å¯Ÿè±¡ã§ããããŸããåäžã®ã¯ã¬ãŒãã ãã§ãªãæšç§»çäŸåé¢ä¿ãåã蟌ãå¯èœæ§ããããããã¬ãã¥ãŒãã¹ãã³ãŒãéã¯ããªãå€ããªãããšããããŸããäžæ¹ã§ãå®å šãª Rust ã³ãŒãã§ããã°è² ã®å¯äœçšã¯éå®çã§ããã§ã¯ãã©ã®ããã«ã¬ãã¥ãŒãã¹ãã§ããããã
Chromium ã¯å°æ¥çã«ãcargo vet ãäžå¿ãšããããã»ã¹ãžç§»è¡ããããšãç®æããŠããŸãã
ãããŸã§ã®éãæ°ããã¯ã¬ãŒãã远å ãããã³ã«ã次ã®ç¹ã確èªããŠããŸãã
- åã¯ã¬ãŒãããªã䜿ãããŠããã®ããçè§£ãããã¯ã¬ãŒãå士ã®é¢ä¿ã¯äœããåã¯ã¬ãŒãã®ãã«ãã·ã¹ãã ã«
build.rsãæç¶ããã¯ããå«ãŸããŠããå Žåã¯ãããããäœã®ããã®ãã®ããææ¡ãããChromium ã®éåžžã®ãã«ãæ¹æ³ãšäºææ§ããããã - åã¯ã¬ãŒããé©åã«ã¡ã³ããã³ã¹ãããŠããããã«èŠãããã確èªãã
- æ¢ç¥ã®è匱æ§ã確èªããããã«
cd third-party/rust/chromium_crates_io; cargo auditã䜿çšããïŒãã®åã«cargo install cargo-auditãå¿ èŠã§ãããç®èãªããšã«ããã«ã¯ã€ã³ã¿ãŒããããã倧éã®äŸåé¢ä¿ãããŠã³ããŒãããããšãå«ãŸããŸã2ïŒ - ãããã
unsafeã³ãŒãã Rule of Two ã®åºæºãæºããããšã確èªãã fsãŸãã¯netAPI ã®äœ¿çšããªãã確èªãã- æªæãæã£ãŠæ¿å ¥ãããå¯èœæ§ã®ããäžèªç¶ãªãã®ããªãããæ¢ããããååãªç²åºŠã§ã³ãŒãå šäœãèªããïŒããã§ 100% ã®å®å šæ§ãçŸå®çã«ç®æãããšã¯ã§ããŸãããã³ãŒãéãå€ãããããšãããããããã§ããïŒ
ãããã¯ãããŸã§ã¬ã€ãã©ã€ã³ã§ã â security@chromium.org ã®ã¬ãã¥ãŒæ
åœè
ãšååããŠããã®ã¯ã¬ãŒããä¿¡é Œã§ãããšç¢ºä¿¡ããããã®é©åãªæ¹æ³ãèŠã€ããŠãã ããã
ã¯ã¬ãŒãã Chromium ãœãŒã¹ã³ãŒãã«ãã§ãã¯ã€ã³ãã
git status ã§ã¯ã次ã確èªã§ããã¯ãã§ãã
//third_party/rust/chromium_crates_ioå ã®ã¯ã¬ãŒãã³ãŒã- ã¡ã¿ããŒã¿ïŒ
BUILD.gnãšREADME.chromiumïŒã//third_party/rust/<crate>/<version>ã«ããããš
åŸè
ã®å Žæã« OWNERS ãã¡ã€ã«ã远å ããŠãã ããã
ããããã¹ãŠããCargo.toml ãš gnrt_config.toml ãžã®å€æŽãšããããŠã Chromium ãªããžããªã«åæ ããŠãã ããã
éèŠ: ãã®ãŸãŸã ãš .gitignore ãã¡ã€ã«ã«ããäžéšã®ãã¡ã€ã«ã ã¹ããããããå¯èœæ§ããããããgit add -f ã䜿çšããå¿
èŠããããŸãã
ãããé²ããäžã§ãã€ã³ã¯ã«ãŒã·ãã§ãªã衚çŸãåå ã§ presubmit ãã§ãã¯ã倱æããããšããããŸããããã¯ãRust ã¯ã¬ãŒãã®ããŒã¿ã«ã¯ git ãã©ã³ãã®ååãå«ãŸããã¡ã§ãããã§ã¯ä»ã§ãå€ãã®ãããžã§ã¯ãã ã€ã³ã¯ã«ãŒã·ãã§ãªãçšèªã䜿ã£ãŠããããã§ãããã®ãããæ¬¡ãå®è¡ãã å¿ èŠããããããããŸããã
infra/update_inclusive_language_presubmit_exempt_dirs.sh > infra/inclusive_language_presubmit_exempt_dirs.txt
git add -p infra/inclusive_language_presubmit_exempt_dirs.txt # èªåã®å€æŽåã远å
ã¯ã¬ãŒããææ°ã®ç¶æ ã«ä¿ã€
ãµãŒãããŒãã£ã® Chromium äŸåé¢ä¿ã® OWNER ã§ããå Žåãããããã»ãã¥ãªãã£ä¿®æ£ãåã蟌ãã§ãã®äŸåé¢ä¿ãææ°ã®ç¶æ ã«ä¿ã€ããšãæåŸ ãããŠããŸããRust ã¯ã¬ãŒãã«ã€ããŠã¯ããããè¿ããã¡ã«èªååã§ããããã«ãªãããšãæåŸ ãããŠããŸãããçŸæç¹ã§ã¯ãä»ã®ãµãŒãããŒãã£äŸåé¢ä¿ãšåæ§ã«ãäŸç¶ãšããŠããªãã®è²¬ä»»ã§ãã
æŒç¿
Chromium ã« uwuify ã远å ããã¯ã¬ãŒãã®ããã©ã«ãæ©èœãç¡å¹ã«ããŠãã ããã ãã®ã¯ã¬ãŒãã¯åºè·ããã Chromium ã§äœ¿çšãããŸãããä¿¡é Œã§ããªãå ¥åã åŠçããããã«ã¯äœ¿çšãããªããã®ãšããŸãã
ïŒæ¬¡ã®æŒç¿ã§ã¯ Chromium ãã uwuify ã䜿çšããŸããããããã°å
ã«é²ãã§ ä»ããããã£ãŠããŸã£ãŠãæ§ããŸããããããã¯ãuwuify ã䜿çšããæ°ãã rust_executable ã¿ãŒã²ãããäœæããŠãããã§ããããïŒ
åè¬è ã¯å€æ°ã®æšç§»çäŸåé¢ä¿ãããŠã³ããŒãããå¿ èŠããããŸãã
å¿ èŠãªã¯ã¬ãŒãã®åèšã¯æ¬¡ã®ãšããã§ãã
instantlock_apiparking_lotparking_lot_coreredox_syscallscopeguardsmallvecuwuify
ããããããã«å€ãããŠã³ããŒãããŠããå Žåã¯ãããã©ã«ãæ©èœãç¡å¹ã«ããã®ã å¿ããŠããå¯èœæ§ãé«ãã§ãã
ãã®ã¯ã¬ãŒãã«ã€ããŠã¯ Daniel Liu ã«æè¬ããŸãã
ãã¹ãŠããŸãšãã â æŒç¿
ãã®æŒç¿ã§ã¯ããããŸã§ã«åŠãã ããšããã¹ãŠçµã¿åãããŠã Chromium ã®ãŸã£ããæ°ããæ©èœã远å ããŸãã
ãããã¯ããããžã¡ã³ãããã®äŸé Œ
人éé¢ããç±åž¯éšæã«æ®ãããã¯ã·ãŒã®ã³ãã¥ããã£ãçºèŠãããŸãããã§ãã ã ãæ©ã圌ãã«ãã¯ã·ãŒåã Chromium ãå±ããããšãéèŠã§ãã
èŠä»¶ã¯ãChromium ã® UI æååããã¹ãŠãã¯ã·ãŒèªã«ç¿»èš³ããããšã§ãã
é©åãªç¿»èš³ãåŸ ã£ãŠããæéã¯ãããŸãããã幞ãã«ããã¯ã·ãŒèªã¯è±èªã«éåžž ã«è¿ãã翻蚳ãè¡ã Rust crate ãããããšãããã£ãŠããŸãã
å®éããã® crate ã¯åã®æŒç¿ã§ããªãããã§ã«ã€ã³ããŒãããŠããŸãã
ïŒãã¡ãããChrome ã®å®éã®ç¿»èš³ã«ã¯äžŠå€ããæ³šæãšå ¥å¿µããå¿ èŠã§ãããã ã¯åºè·ããªãã§ãã ããïŒïŒ
æé
ResourceBundle::MaybeMangleLocalizedString ã倿ŽããŠã衚瀺åã«ãã¹ãŠ ã®æååã uwuåããããã«ããŠãã ããããã®ç¹å¥ãª Chromium ãã«ãã§ã¯ã mangle_localized_strings_ ã®èšå®ã«é¢ä¿ãªããåžžã«ãããè¡ãããã«ãã å¿
èŠããããŸãã
ãããã®æŒç¿ãéããŠãã¹ãŠãæ£ããã§ããŠããã°ãããã§ãšãããããŸããã ãªãã¯ãã¯ã·ãŒåã Chrome ãäœãäžããããšã«ãªããŸãïŒ
- UTF-16 ãš UTF-8ãRust ã®æååã¯åžžã« UTF-8 ã§ããããšããåŠçã¯èªèã ãŠããå¿
èŠããããŸãããã®ããéåžžã¯ã
base::UTF16ToUTF8ã䜿ã£ãŠ C++ åŽã§å€æãããŸãæ»ãæ¹ããããšå€æããã§ãããã - åŠçã Rust åŽã§å€æããããšã«ããå Žåã¯ã
String::from_utf16ã ãšã©ãŒãã³ããªã³ã°ããããŠå€æ°ã® u16 ã転éã§ãã CXX 察å¿å ã®ã© ãã䜿ãããæ€èšããå¿ èŠããããŸãã - åŠç㯠C++/Rust éã®å¢çããããã€ãç°ãªãæ¹æ³ã§èšèšãããããããŸããã ããšãã°ãæååã倿ž¡ãã§åãåãå€ãšããŠè¿ãæ¹æ³ããæååãžã®å¯å€åç
§ ãåãåãæ¹æ³ã§ããå¯å€åç
§ã䜿ãå ŽåãCXX ã¯ããããåŠçã«
Pinã䜿ãå¿ èŠããããšäŒããã§ããããPinãäœãããã®ããã ã㊠C++ ããŒã¿ãžã®å¯å€åç §ã«å¯Ÿã㊠CXX ããããå¿ èŠãšããçç±ã説æã ãå¿ èŠããããããããŸãããçãã¯ãC++ ã®ããŒã¿ã«ã¯èªå·±åç §ãã€ã³ã¿ã å«ãŸããŠããå¯èœæ§ããããããRust ã®ããŒã¿ã®ããã«ç§»åãããããšãã§ã ãªãããã§ãã ResourceBundle::MaybeMangleLocalizedStringãå«ã C++ ã¿ãŒã²ããã¯ãrust_static_libraryã¿ãŒã²ããã«äŸåããå¿ èŠããããŸããåŠçã¯ããã ããã§ã«ãããè¡ã£ãŠããŸããrust_static_libraryã¿ãŒã²ããã¯ã次ã«äŸåããå¿ èŠããããŸãã//third_party/rust/uwuify/v0_2:lib
æŒç¿ã®è§£ç
Chromium ã®æŒç¿ã®è§£çã¯ããã®äžé£ã® CL ã§ç¢ºèªã§ããŸãã
ãŸãããããã»ããã®é©çšã Chromium ã®ã³ã¢ã³ãŒããšã®çµ±åãå¿
èŠãšããªããã¹ã¿ã³ãã¢ãã³ãã®è§£çã®ã»ããããå Žåã¯ã[Chromium å
ã® //chromium/src/codelabs/rust ãµããã£ã¬ã¯ããª]ã§ç¢ºèªã§ããŸãã
ãã¢ã¡ã¿ã« Rust ãžãããã
ããã¯ãã¢ã¡ã¿ã« Rust ã«é¢ããåç¬ã® 1 æ¥ã³ãŒã¹ã§ãããRust ã®åºç€ ïŒãããã Comprehensive Rust ã³ãŒã¹ãä¿®äºããŠïŒã«æ £ããŠããŠãã§ããã° C ãªã©ã®ä»ã®èšèªã§ãã¢ã¡ã¿ã«ããã°ã©ãã³ã°ã®çµéšããã人ã察象ãšã㊠ããŸãã
仿¥ã¯ããã¢ã¡ã¿ã«ãRustãã€ãŸããã®äžã« OS ããªãç¶æ ã§ Rust ã³ãŒãã å®è¡ããããšã«ã€ããŠè©±ããŸããå 容ã¯ããã€ãã®ããŒãã«åãããŠããŸã:
no_stdRust ãšã¯äœãïŒ- ãã€ã¯ãã³ã³ãããŒã©ãŒåããã¡ãŒã ãŠã§ã¢ã®äœæã
- ã¢ããªã±ãŒã·ã§ã³ããã»ããµåãã®ããŒãããŒã㌠/ ã«ãŒãã«ã³ãŒãã®äœæã
- ãã¢ã¡ã¿ã« Rust éçºã«åœ¹ç«ã€ããã€ãã®ã¯ã¬ãŒãã
ãã®ã³ãŒã¹ã®ãã€ã¯ãã³ã³ãããŒã©ãŒã®ããŒãã§ã¯ã BBC micro:bit v2 ãäŸãšããŠäœ¿çšããŸããããã¯ã Nordic nRF52833 ãã€ã¯ãã³ã³ãããŒã©ãŒãããŒã¹ã«ãã éçºããŒã ã§ãããã€ãã® LED ãšãã¿ã³ã I2C æ¥ç¶ã®å é床èšãšã³ã³ãã¹ããããŠãªã³ããŒãã® SWD ãããã¬ãŒãåã㊠ããŸãã
ãŸããåŸã§å¿ èŠã«ãªãããã€ãã®ããŒã«ãã€ã³ã¹ããŒã«ããŸããããgLinux ãŸã㯠Debian ã®å Žå:
sudo apt install gdb-multiarch libudev-dev picocom pkg-config qemu-system-arm build-essential
rustup update
rustup target add aarch64-unknown-none thumbv7em-none-eabihf
rustup component add llvm-tools-preview
cargo install cargo-binutils
curl --proto '=https' --tlsv1.2 -LsSf https://github.com/probe-rs/probe-rs/releases/latest/download/probe-rs-tools-installer.sh | sh
ãããŠãplugdev ã°ã«ãŒãã®ãŠãŒã¶ãŒã micro:bit ããã°ã©ããŒã«ã¢ã¯ã»ã¹ ã§ããããã«ããŸã:
echo 'SUBSYSTEM=="hidraw", ATTRS{idVendor}=="0d28", MODE="0660", GROUP="logindev", TAG+="uaccess"' |\
sudo tee /etc/udev/rules.d/50-microbit.rules
sudo udevadm control --reload-rules
ããã€ã¹ãå©çšå¯èœã§ããã°ãlsusb ã®åºåã« âNXP ARM mbedâ ãšè¡šç€ºããã ã¯ãã§ããChromebook äžã® Linux ç°å¢ã䜿çšããŠããå Žåã¯ã chrome://os-settings/crostini/sharedUsbDevices ãä»ã㊠USB ããã€ã¹ã Linux ãšå
±æããå¿
èŠããããŸãã
MacOS ã®å Žå:
xcode-select --install
brew install gdb picocom qemu
rustup update
rustup target add aarch64-unknown-none thumbv7em-none-eabihf
rustup component add llvm-tools-preview
cargo install cargo-binutils
curl --proto '=https' --tlsv1.2 -LsSf https://github.com/probe-rs/probe-rs/releases/latest/download/probe-rs-tools-installer.sh | sh
no_std
|
|
|
|
|---|---|---|
|
|
|
HashMap㯠RNG ã«äŸåããŸããstdã¯coreãšallocã®äž¡æ¹ã®å 容ãåãšã¯ã¹ããŒãããŸãã
æå°éã® no_std ããã°ã©ã
// Copyright 2023 Google LLC // SPDX-License-Identifier: Apache-2.0 #![no_main] #![no_std] use core::panic::PanicInfo; #[panic_handler] fn panic(_panic: &PanicInfo) -> ! { loop {} }
- ããã¯ç©ºã®ãã€ããªã«ã³ã³ãã€ã«ãããŸãã
std㯠panic ãã³ãã©ãæäŸããŸããããããªãå Žåã¯ãèªåã§çšæããªããã°ãªããŸããã- ããã¯
panic-haltãªã©ã®å¥ã®ã¯ã¬ãŒãã«ãã£ãŠæäŸããããšãã§ããŸãã - ã¿ãŒã²ããã«ãã£ãŠã¯ã
eh_personalityã«é¢ãããšã©ãŒãåé¿ããããã«ãpanic = "abort"ãæå®ããŠã³ã³ãã€ã«ããå¿ èŠãããå ŽåããããŸãã mainããã®ä»ã®ãšã³ããªãã€ã³ãã¯ååšããªãããšã«æ³šæããŠãã ãããç¬èªã® ãšã³ããªãã€ã³ããèªåã§å®çŸ©ããå¿ èŠããããŸããéåžžãããã«ã¯ Rust ã³ãŒãã å®è¡ã§ããç¶æ ã«ããããã®ãªã³ã«ãŒã¹ã¯ãªãããšãããããã®ã¢ã»ã³ããªã³ãŒããé¢ãããŸãã
alloc
alloc ã䜿çšããã«ã¯ã ã°ããŒãã«ïŒããŒãïŒã¢ãã±ãŒã¿ ãå®è£
ããå¿
èŠããããŸãã
// èäœæš© 2023 Google LLC // SPDX-License-Identifier: Apache-2.0 #![no_main] #![no_std] extern crate alloc; extern crate panic_halt as _; use alloc::string::ToString; use alloc::vec::Vec; use buddy_system_allocator::LockedHeap; #[global_allocator] static HEAP_ALLOCATOR: LockedHeap<32> = LockedHeap::<32>::new(); const HEAP_SIZE: usize = 65536; static mut HEAP: [u8; HEAP_SIZE] = [0; HEAP_SIZE]; pub fn entry() { // SAFETY: `HEAP` is only used here and `entry` is only called once. unsafe { // Give the allocator some memory to allocate. HEAP_ALLOCATOR.lock().init(&raw mut HEAP as usize, HEAP_SIZE); } // Now we can do things that require heap allocation. let mut v = Vec::new(); v.push("A string".to_string()); }
buddy_system_allocatorã¯åºæ¬çãªããã£ã·ã¹ãã ã¢ãã±ãŒã¿ãå®è£ ããã¯ã¬ãŒãã§ããã»ãã®ã¯ã¬ãŒããå©çšã§ããŸãããèªåã§äœæããããæ¢åã®ã¢ãã±ãŒã¿ã«çµã¿èŸŒãã ãããããšãã§ããŸããLockedHeapã® const ãã©ã¡ãŒã¿ã¯ã¢ãã±ãŒã¿ã®æå€§ãªãŒããŒã§ããã€ãŸãã ãã®å Žåã¯æå€§ 2**32 ãã€ãã®é åãå²ãåœãŠãããŸãã- äŸåããªãŒå
ã®ããããã®ã¯ã¬ãŒãã
allocã«äŸåããŠããå Žåã¯ããã€ããªå ã« ã°ããŒãã«ã¢ãã±ãŒã¿ãã¡ããã© 1 ã€å®çŸ©ããŠããå¿ èŠããããŸããéåžžããã㯠æäžäœã®ãã€ããªã¯ã¬ãŒãã§è¡ããŸãã extern crate panic_halt as _ã¯ãpanic_haltã¯ã¬ãŒãããªã³ã¯ãããŠãã® panic ãã³ãã©ãå©çšã§ããããã«ããããã«å¿ èŠã§ãã- ãã®äŸã¯ãšã³ããªãã€ã³ããæããªãããããã«ãã¯ã§ããŸããå®è¡ã¯ã§ããŸããã
ãã€ã¯ãã³ã³ãããŒã©
cortex_m_rt ã¯ã¬ãŒãã¯ãïŒã»ãã«ãããã€ãã®æ©èœããããŸããïŒCortex M ãã€ã¯ãã³ã³ãããŒã©çšã®ãªã»ãããã³ãã©ãæäŸããŸãã
// Copyright 2023 Google LLC // SPDX-License-Identifier: Apache-2.0 #![no_main] #![no_std] extern crate panic_halt as _; mod interrupts; use cortex_m_rt::entry; #[entry] fn main() -> ! { loop {} }
次ã«ãæœè±¡åã®ã¬ãã«ãåŸã ã«äžããªãããåšèŸºæ©åšã«ã¢ã¯ã»ã¹ããæ¹æ³ã èŠãŠãããŸãã
cortex_m_rt::entryãã¯ãã§ã¯ã颿°ã®åãfn() -> !ã§ããå¿ èŠããããŸããããã¯ããªã»ãããã³ãã©ã«æ»ãããšã«ã¯æå³ããªãããã§ãã- äŸã
cargo embed --bin minimalã§å®è¡ããŸã
çã® MMIO
ã»ãšãã©ã®ãã€ã¯ãã³ã³ãããŒã©ãŒã¯ãã¡ã¢ãªãããã I/O ãä»ããŠåšèŸºæ©åšã«ã¢ã¯ã»ã¹ããŸããmicro:bit ã® LED ãç¹ç¯ããŠã¿ãŸããã:
// èäœæš© 2023 Google LLC // SPDX-License-Identifier: Apache-2.0 #![no_main] #![no_std] extern crate panic_halt as _; mod interrupts; use core::mem::size_of; use cortex_m_rt::entry; /// GPIO port 0 peripheral address const GPIO_P0: usize = 0x5000_0000; // GPIO peripheral offsets const PIN_CNF: usize = 0x700; const OUTSET: usize = 0x508; const OUTCLR: usize = 0x50c; // PIN_CNF fields const DIR_OUTPUT: u32 = 0x1; const INPUT_DISCONNECT: u32 = 0x1 << 1; const PULL_DISABLED: u32 = 0x0 << 2; const DRIVE_S0S1: u32 = 0x0 << 8; const SENSE_DISABLED: u32 = 0x0 << 16; #[entry] fn main() -> ! { // Configure GPIO 0 pins 21 and 28 as push-pull outputs. let pin_cnf_21 = (GPIO_P0 + PIN_CNF + 21 * size_of::<u32>()) as *mut u32; let pin_cnf_28 = (GPIO_P0 + PIN_CNF + 28 * size_of::<u32>()) as *mut u32; // SAFETY: The pointers are to valid peripheral control registers, and no // aliases exist. unsafe { pin_cnf_21.write_volatile( DIR_OUTPUT | INPUT_DISCONNECT | PULL_DISABLED | DRIVE_S0S1 | SENSE_DISABLED, ); pin_cnf_28.write_volatile( DIR_OUTPUT | INPUT_DISCONNECT | PULL_DISABLED | DRIVE_S0S1 | SENSE_DISABLED, ); } // Set pin 28 low and pin 21 high to turn the LED on. let gpio0_outset = (GPIO_P0 + OUTSET) as *mut u32; let gpio0_outclr = (GPIO_P0 + OUTCLR) as *mut u32; // SAFETY: The pointers are to valid peripheral control registers, and no // aliases exist. unsafe { gpio0_outclr.write_volatile(1 << 28); gpio0_outset.write_volatile(1 << 21); } loop {} }
- GPIO 0 ã®ãã³ 21 㯠LED ãããªã¯ã¹ã®æåã®åã«æ¥ç¶ãããŠããããã³ 28 㯠æåã®è¡ã«æ¥ç¶ãããŠããŸãã
次ã®ã³ãã³ãã§ãã®äŸãå®è¡ããŸã:
cargo embed --bin mmio
ããªãã§ã©ã«ã¢ã¯ã»ã¹ã¯ã¬ãŒã
svd2rust ã¯ãCMSIS-SVD ãã¡ã€ã«ãããã¡ã¢ãªããããããããªãã§ã©ã«åãã®ã»ãŒå®å
šãª Rust ã©ãããŒãçæããŸãã
// Copyright 2023 Google LLC // SPDX-License-Identifier: Apache-2.0 #![no_main] #![no_std] extern crate panic_halt as _; use cortex_m_rt::entry; use nrf52833_pac::Peripherals; #[entry] fn main() -> ! { let p = Peripherals::take().unwrap(); let gpio0 = p.P0; // Configure GPIO 0 pins 21 and 28 as push-pull outputs. gpio0.pin_cnf[21].write(|w| { w.dir().output(); w.input().disconnect(); w.pull().disabled(); w.drive().s0s1(); w.sense().disabled(); w }); gpio0.pin_cnf[28].write(|w| { w.dir().output(); w.input().disconnect(); w.pull().disabled(); w.drive().s0s1(); w.sense().disabled(); w }); // Set pin 28 low and pin 21 high to turn the LED on. gpio0.outclr.write(|w| w.pin28().clear()); gpio0.outset.write(|w| w.pin21().set()); loop {} }
- SVDïŒSystem View DescriptionïŒãã¡ã€ã«ã¯ãéåžžã¯åå°äœãã³ããŒããæäŸããã XML ãã¡ã€ã«ã§ãããããã€ã¹ã®ã¡ã¢ãªããããèšè¿°ããŸãã
- ãããã¯ããªãã§ã©ã«ãã¬ãžã¹ã¿ããã£ãŒã«ããå€ããšã«æŽçãããŠãããååã説æãã¢ãã¬ã¹ãªã©ãå«ãŸããŸãã
- SVD ãã¡ã€ã«ã«ã¯ãã°ãã°ãã°ããããäžå®å šã§ãããããã誀ããä¿®æ£ããäžè¶³ããŠãã詳现ã远å ããŠãçæãããã¯ã¬ãŒããå ¬éããããŸããŸãªãããžã§ã¯ãããããŸãã
cortex-m-rtã¯ãä»ã®æ©èœã«å ããŠãã¯ã¿ããŒãã«ãæäŸããŸããcargo install cargo-binutilsãå®è¡ãããšãcargo objdump --bin pac -- -d --no-show-raw-insnãå®è¡ããŠçæããããã€ããªã確èªã§ããŸãã
次ã®ã³ãã³ãã§ãã®äŸãå®è¡ããŸãã
cargo embed --bin pac
HAL ã¯ã¬ãŒã
HAL ã¯ã¬ãŒã ã¯å€ãã®ãã€ã¯ãã³ã³ãããŒã©ãŒåãã«ã ããŸããŸãªåšèŸºæ©åšã®ã©ãããŒãæäŸããŠããŸãããããã¯äžè¬ã« embedded-hal ã®ãã¬ã€ããå®è£
ããŠããŸãã
// èäœæš© 2023 Google LLC // SPDX-License-Identifier: Apache-2.0 #![no_main] #![no_std] extern crate panic_halt as _; use cortex_m_rt::entry; use embedded_hal::digital::OutputPin; use nrf52833_hal::gpio::{Level, p0}; use nrf52833_hal::pac::Peripherals; #[entry] fn main() -> ! { let p = Peripherals::take().unwrap(); // Create HAL wrapper for GPIO port 0. let gpio0 = p0::Parts::new(p.P0); // Configure GPIO 0 pins 21 and 28 as push-pull outputs. let mut col1 = gpio0.p0_28.into_push_pull_output(Level::High); let mut row1 = gpio0.p0_21.into_push_pull_output(Level::Low); // Set pin 28 low and pin 21 high to turn the LED on. col1.set_low().unwrap(); row1.set_high().unwrap(); loop {} }
set_lowãšset_highã¯ãembedded_halã®OutputPinãã¬ã€ãã®ã¡ãœããã§ãã- HAL ã¯ã¬ãŒãã¯ãå€ãã® Cortex-M ããã³ RISC-V ããã€ã¹åãã«æäŸãããŠãããããŸããŸãª STM32ãGD32ãnRFãNXPãMSP430ãAVRãPIC ãã€ã¯ãã³ã³ãããŒã©ãŒã«å¯Ÿå¿ããŠããŸãã
次ã®ã³ãã³ãã§äŸãå®è¡ããŸã:
cargo embed --bin hal
ããŒããµããŒãã¯ã¬ãŒã
ããŒããµããŒãã¯ã¬ãŒãã¯ãå©äŸ¿æ§ã®ããã«ãç¹å®ã®ããŒãåãã®ãããªãã©ãããŒå±€ãæäŸããŸãã
// èäœæš© 2023 Google LLC // SPDX-License-Identifier: Apache-2.0 #![no_main] #![no_std] extern crate panic_halt as _; use cortex_m_rt::entry; use embedded_hal::digital::OutputPin; use microbit::Board; #[entry] fn main() -> ! { let mut board = Board::take().unwrap(); board.display_pins.col1.set_low().unwrap(); board.display_pins.row1.set_high().unwrap(); loop {} }
- ãã®å ŽåãããŒããµããŒãã¯ã¬ãŒãã¯ããã䜿ããããååãšãå°ãã®åæåãæäŸããŠããã ãã§ãã
- ãã®ã¯ã¬ãŒãã«ã¯ããã€ã¯ãã³ã³ãããŒã©ãŒæ¬äœä»¥å€ã®ãããŒãäžã®äžéšã®ããã€ã¹çšãã©ã€ããŒãå«ãŸããããšããããŸãã
microbit-v2ã«ã¯ãLED ãããªã¯ã¹çšã®ã·ã³ãã«ãªãã©ã€ããŒãå«ãŸããŠããŸãã
次ã®ã³ãã³ãã§ãã®äŸãå®è¡ããŸã:
cargo embed --bin board_support
åç¶æ ãã¿ãŒã³
// Copyright 2023 Google LLC // SPDX-License-Identifier: Apache-2.0 #[entry] fn main() -> ! { let p = Peripherals::take().unwrap(); let gpio0 = p0::Parts::new(p.P0); let pin: P0_01<Disconnected> = gpio0.p0_01; // let gpio0_01_again = gpio0.p0_01; // Error, moved. let mut pin_input: P0_01<Input<Floating>> = pin.into_floating_input(); if pin_input.is_high().unwrap() { // ... } let mut pin_output: P0_01<Output<OpenDrain>> = pin_input .into_open_drain_output(OpenDrainConfig::Disconnect0Standard1, Level::Low); pin_output.set_high().unwrap(); // pin_input.is_high(); // Error, moved. let _pin2: P0_02<Output<OpenDrain>> = gpio0 .p0_02 .into_open_drain_output(OpenDrainConfig::Disconnect0Standard1, Level::Low); let _pin3: P0_03<Output<PushPull>> = gpio0.p0_03.into_push_pull_output(Level::Low); loop {} }
- ãã³ã¯
CopyãCloneãå®è£ ããŠããªããããããããã«ã€ããŠååšã§ããã€ã³ã¹ã¿ã³ã¹ã¯ 1 ã€ã ãã§ãããã£ããããŒãæ§é äœãããã³ãã ãŒãããããšãã»ãã®èª°ããããååŸã§ããŸããã - ãã³ã®èšå®ã倿Žãããšå€ããã³ã€ã³ã¹ã¿ã³ã¹ãæ¶è²»ãããããããã®åŸã¯å€ãã€ã³ã¹ã¿ã³ã¹ã䜿ããŸããã
- å€ã®åã¯ããã®å€ãã©ã®ç¶æ ã«ãããã瀺ããŸããããšãã°ããã®å Žå㯠GPIO ãã³ã®èšå®ç¶æ ã§ããããã«ãããç¶æ æ©æ¢°ãåã·ã¹ãã ã«ãšã³ã³ãŒããããå ã«é©åã«èšå®ããããšãªãç¹å®ã®æ¹æ³ã§ãã³ã䜿ãããšããªãããšãä¿èšŒãããŸããäžæ£ãªç¶æ é·ç§»ã¯ã³ã³ãã€ã«æã«æ€åºãããŸãã
- å
¥åãã³ã§ã¯
is_highãåŒã³åºããåºåãã³ã§ã¯set_highãåŒã³åºããŸããããã®éã¯ã§ããŸããã - å€ãã® HAL ã¯ã¬ãŒãã¯ãã®ãã¿ãŒã³ã«åŸã£ãŠããŸãã
embedded-hal
embedded-hal ã¯ã¬ãŒãã¯ãäžè¬çãªãã€ã¯ãã³ã³ãããŒã©ãŒåšèŸºæ©åšã察象ãšããè€æ°ã®ãã¬ã€ããæäŸããŸãã
- GPIO
- PWM
- ãã£ã¬ã€ã¿ã€ããŒ
- I2C ããã³ SPI ã®ãã¹ãšããã€ã¹
ãã€ãã¹ããªãŒã ïŒäŸ: UARTïŒãCAN ãã¹ãRNG åãã®åæ§ã®ãã¬ã€ãã¯ããããã embedded-ioãembedded-canãrand_core ã«åãããŠããŸãã
ãã®åŸãä»ã®ã¯ã¬ãŒãããããã®ãã¬ã€ãã«åºã¥ã㊠drivers ãå®è£ ããŸããããšãã°ãå é床èšãã©ã€ããŒã«ã¯ I2C ãŸã㯠SPI ããã€ã¹ã®ã€ã³ã¹ã¿ã³ã¹ãå¿ èŠã«ãªãå ŽåããããŸãã
- ãããã®ãã¬ã€ãã¯åšèŸºæ©åšã®äœ¿çšã察象ãšããŠããŸãããåæåãèšå®ã¯å¯Ÿè±¡ãšããŠããŸãããåæåãšèšå®ã¯ãã©ãããã©ãŒã äŸåæ§ãéåžžã«é«ãããã§ãã
- å€ãã®ãã€ã¯ãã³ã³ãããŒã©ãŒåãã®å®è£ ã«å ããRaspberry Pi äžã® Linux ã®ãããªä»ã®ãã©ãããã©ãŒã åãã®å®è£ ããããŸãã
embedded-hal-asyncã¯ããããã®ãã¬ã€ãã® async çãæäŸããŸããembedded-hal-nbã¯ãnbã¯ã¬ãŒãã«åºã¥ãããã³ããããã³ã° I/O ãžã®å¥ã®ã¢ãããŒããæäŸããŸãã
probe-rs ãš cargo-embed
probe-rs ã¯ãOpenOCD ã«äŒŒãŠããŸãããããç·å¯ã«çµ±åããããçµã¿èŸŒã¿ãããã°åãã®äŸ¿å©ãªããŒã«ã»ããã§ãã
- CMSIS-DAPãST-LinkãJ-Link ãããŒãçµç±ã® SWDïŒSerial Wire DebugïŒãš JTAG
- GDB ã¹ã¿ããš Microsoft DAPïŒDebug Adapter ProtocolïŒãµãŒããŒ
- Cargo çµ±å
cargo-embed ã¯ããã€ããªã®ãã«ããšãã©ãã·ã¥ãRTTïŒReal Time TransfersïŒåºåã®ãã°èšé²ãGDB ãžã®æ¥ç¶ãè¡ãããã® cargo ãµãã³ãã³ãã§ããèšå®ã¯ããããžã§ã¯ããã£ã¬ã¯ããªå
ã® Embed.toml ãã¡ã€ã«ã§è¡ããŸãã
- CMSIS-DAP ã¯ãã€ã³ãµãŒããããããã¬ãŒãããŸããŸãª Arm Cortex ããã»ããµã® CoreSight Debug Access Port ã«ã¢ã¯ã»ã¹ããããã®ãUSB äžã® Arm æšæºãããã³ã«ã§ããããã¯ãBBC micro:bit ã®ãªã³ããŒããããã¬ãŒã§äœ¿ãããŠãããã®ã§ãã
- ST-Link 㯠ST Microelectronics ã®ã€ã³ãµãŒããããããã¬ãŒè£œå矀ã§ãJ-Link 㯠SEGGER ã®è£œå矀ã§ãã
- Debug Access Port ã¯éåžžã5 ãã³ã® JTAG ã€ã³ã¿ãŒãã§ãŒã¹ãŸã㯠2 ãã³ã® Serial Wire Debug ã®ããããã§ãã
- probe-rs ã¯ãå¿ èŠã«å¿ããŠèªåã®ããŒã«ã«çµã¿èŸŒããã©ã€ãã©ãªã§ãã
- Microsoft Debug Adapter Protocol ã«ãããVSCode ããã®ä»ã® IDE ã¯ããµããŒããããŠããä»»æã® ãã€ã¯ãã³ã³ãããŒã©ãŒäžã§å®è¡ãããã³ãŒãããããã°ã§ããŸãã
- cargo-embed ã¯ãprobe-rs ã©ã€ãã©ãªã䜿ã£ãŠãã«ãããããã€ããªã§ãã
- RTTïŒReal Time TransfersïŒã¯ãè€æ°ã®ãªã³ã°ãããã¡ãä»ããŠãããã° ãã¹ããšã¿ãŒã²ããã®éã§ããŒã¿ã転éããä»çµã¿ã§ãã
ãããã°
Embed.toml:
[default.general]
chip = "nrf52833_xxAA"
[debug.gdb]
enabled = true
src/bare-metal/microcontrollers/examples/ é
äžã® 1 ã€ã®ã¿ãŒããã«ã§:
cargo embed --bin board_support debug
åããã£ã¬ã¯ããªã®å¥ã®ã¿ãŒããã«ã§:
gLinux ãŸã㯠Debian ã®å Žå:
gdb-multiarch target/thumbv7em-none-eabihf/debug/board_support --eval-command="target remote :1338"
MacOS ã®å Žå:
arm-none-eabi-gdb target/thumbv7em-none-eabihf/debug/board_support --eval-command="target remote :1338"
GDB ã§ã次ãå®è¡ããŠã¿ãŠãã ãã:
b src/bin/board_support.rs:29
b src/bin/board_support.rs:30
b src/bin/board_support.rs:32
c
c
c
ãã®ä»ã®ãããžã§ã¯ã
- RTIC
- ããªã¢ã«ã¿ã€ã å²ã蟌ã¿é§åã³ã³ã«ã¬ã³ã·ãŒãã
- å ±æãªãœãŒã¹ç®¡çãã¡ãã»ãŒãžããã·ã³ã°ãã¿ã¹ã¯ã¹ã±ãžã¥ãŒãªã³ã°ãã¿ã€ããŒãã¥ãŒã
- Embassy
- åªå
床ãã¿ã€ããŒããããã¯ãŒãã³ã°ãUSB ãåãã
asyncãšã°ãŒãã¥ãŒã¿ãŒã
- åªå
床ãã¿ã€ããŒããããã¯ãŒãã³ã°ãUSB ãåãã
- TockOS
- ããªãšã³ããã£ãã¹ã±ãžã¥ãŒãªã³ã°ãšã¡ã¢ãªä¿è·ãŠããã ã®ãµããŒããåãããã»ãã¥ãªãã£éèŠã® RTOSã
- Hubris
- ã¡ã¢ãªä¿è·ãéç¹æš©ãã©ã€ããŒãIPC ãåããã Oxide Computer Company ã®ãã€ã¯ãã«ãŒãã« RTOSã
- Bindings for FreeRTOS
- FreeRTOS çšãã€ã³ãã£ã³ã°ã
äžéšã®ãã©ãããã©ãŒã ã«ã¯ std å®è£
ããããŸããããšãã° esp-idfã
- RTIC 㯠RTOS ãšãã³ã³ã«ã¬ã³ã·ãŒãã¬ãŒã ã¯ãŒã¯ãšãèŠãªããŸãã
- HAL ã¯å«ãŸããŠããŸããã
- æ¬æ Œçãªã«ãŒãã«ã§ã¯ãªããã¹ã±ãžã¥ãŒãªã³ã°ã« Cortex-M NVICïŒNested Virtual Interrupt ControllerïŒã䜿çšããŸãã
- Cortex-M ã®ã¿ã
- Google 㯠Titan ã»ãã¥ãªãã£ããŒåãã« Haven ãã€ã¯ãã³ã³ãããŒã©ãŒäžã§ TockOS ã䜿çšããŠããŸãã
- FreeRTOS ã®å€§éšå㯠C ã§æžãããŠããŸãããã¢ããªã±ãŒã·ã§ã³ãèšè¿°ããããã® Rust ãã€ã³ãã£ã³ã°ããããŸãã
æŒç¿
I2C ã³ã³ãã¹ããæ¹è§ãèªã¿åãããã®èªã¿åãå€ãã·ãªã¢ã«ããŒãã«èšé²ããŸãã
æŒç¿ã確èªããããçšæãããŠãã solutions ãèŠãããšãã§ããŸãã
ã³ã³ãã¹
I2C ã³ã³ãã¹ããæ¹äœãèªã¿åãããã®æž¬å®å€ãã·ãªã¢ã« ããŒãã«èšé²ããŸããæéãããã°ãäœããã®åœ¢ã§ LED ã«è¡šç€ºãããã ãã¿ã³ãäœããã®åœ¢ã§äœ¿ã£ããããŠã¿ãŠãã ããã
ãã³ã:
lsm303agrãšmicrobit-v2ã¯ã¬ãŒãã®ããã¥ã¡ã³ããããã³ micro:bit ããŒããŠã§ã¢ ã 確èªããŠãã ããã- LSM303AGR æ £æ§èšæž¬ãŠãããã¯ãå éš I2C ãã¹ã«æ¥ç¶ãããŠããŸãã
- TWI 㯠I2C ã®å¥åãªã®ã§ãI2C ãã¹ã¿ãŒããªãã§ã©ã«ã¯ TWIM ãšåŒã°ããŸãã
- LSM303AGR ãã©ã€ãã«ã¯ã
embedded_hal::i2c::I2cãã¬ã€ããå®è£ ãããã®ãå¿ èŠã§ããããã¯microbit::hal::Twimæ§é äœãå®è£ ããŠããŸãã - ããŸããŸãªãã³ãããªãã§ã©ã«çšã®ãã£ãŒã«ããæã€
microbit::Boardæ§é äœã䜿ããŸãã - å¿ èŠã§ããã° nRF52833 ããŒã¿ã·ãŒã ãåç §ããŠãããŸããŸãããããã®æŒç¿ã§ã¯å¿ èŠãªãã¯ãã§ãã
æŒç¿ãã³ãã¬ãŒã ãããŠã³ããŒããã compass ãã£ã¬ã¯ããªã§æ¬¡ã®ãã¡ã€ã«ã確èªããŠãã ããã
src/main.rs:
// Copyright 2023 Google LLC // SPDX-License-Identifier: Apache-2.0 #![no_main] #![no_std] extern crate panic_halt as _; use core::fmt::Write; use cortex_m_rt::entry; use microbit::{hal::{Delay, uarte::{Baudrate, Parity, Uarte}}, Board}; #[entry] fn main() -> ! { let mut board = Board::take().unwrap(); // Configure serial port. let mut serial = Uarte::new( board.UARTE0, board.uart.into(), Parity::EXCLUDED, Baudrate::BAUD115200, ); // Use the system timer as a delay provider. let mut delay = Delay::new(board.SYST); // Set up the I2C controller and Inertial Measurement Unit. // TODO writeln!(serial, "Ready.").unwrap(); loop { // Read compass data and log it to the serial port. // TODO } }
Cargo.tomlïŒããã¯å€æŽããå¿ èŠã¯ãªãã¯ãã§ãïŒ:
[workspace]
[package]
name = "compass"
version = "0.1.0"
edition = "2024"
publish = false
[dependencies]
cortex-m-rt = "0.7.5"
embedded-hal = "1.0.0"
lsm303agr = "1.1.0"
microbit-v2 = "0.16.0"
panic-halt = "1.0.0"
Embed.tomlïŒããã¯å€æŽããå¿ èŠã¯ãªãã¯ãã§ãïŒ:
[default.general]
chip = "nrf52833_xxAA"
[debug.gdb]
enabled = true
[debug.reset]
halt_afterwards = true
.cargo/config.tomlïŒããã¯å€æŽããå¿ èŠã¯ãªãã¯ãã§ãïŒ:
[build]
target = "thumbv7em-none-eabihf" # Cortex-M4F
[target.'cfg(all(target_arch = "arm", target_os = "none"))']
rustflags = ["-C", "link-arg=-Tlink.x"]
Linux ã§ã¯ã次ã®ããã«ããŠã·ãªã¢ã«åºåã確èªã§ããŸã:
picocom --baud 115200 --imap lfcrlf /dev/ttyACM0
ãŸã㯠Mac OS ã§ã¯æ¬¡ã®ããã«ãªããŸãïŒããã€ã¹åã¯å€å°ç°ãªãå ŽåããããŸãïŒ:
picocom --baud 115200 --imap lfcrlf /dev/tty.usbmodem14502
picocom ãçµäºããã«ã¯ Ctrl+A Ctrl+Q ã䜿ããŸãã
ãã¢ã¡ã¿ã« Rust ååã®æŒç¿
ã³ã³ãã¹
// Google LLC ã® Copyright 2023 // SPDX-License-Identifier: Apache-2.0 #![no_main] #![no_std] extern crate panic_halt as _; use core::fmt::Write; use cortex_m_rt::entry; use embedded_hal::digital::InputPin; use lsm303agr::{ AccelMode, AccelOutputDataRate, Lsm303agr, MagMode, MagOutputDataRate, }; use microbit::Board; use microbit::display::blocking::Display; use microbit::hal::twim::Twim; use microbit::hal::uarte::{Baudrate, Parity, Uarte}; use microbit::hal::{Delay, Timer}; use microbit::pac::twim0::frequency::FREQUENCY_A; const COMPASS_SCALE: i32 = 30000; const ACCELEROMETER_SCALE: i32 = 700; #[entry] fn main() -> ! { let mut board = Board::take().unwrap(); // Configure serial port. let mut serial = Uarte::new( board.UARTE0, board.uart.into(), Parity::EXCLUDED, Baudrate::BAUD115200, ); // Use the system timer as a delay provider. let mut delay = Delay::new(board.SYST); // Set up the I2C controller and Inertial Measurement Unit. writeln!(serial, "Setting up IMU...").unwrap(); let i2c = Twim::new(board.TWIM0, board.i2c_internal.into(), FREQUENCY_A::K100); let mut imu = Lsm303agr::new_with_i2c(i2c); imu.init().unwrap(); imu.set_mag_mode_and_odr( &mut delay, MagMode::HighResolution, MagOutputDataRate::Hz50, ) .unwrap(); imu.set_accel_mode_and_odr( &mut delay, AccelMode::Normal, AccelOutputDataRate::Hz50, ) .unwrap(); let mut imu = imu.into_mag_continuous().ok().unwrap(); // Set up display and timer. let mut timer = Timer::new(board.TIMER0); let mut display = Display::new(board.display_pins); let mut mode = Mode::Compass; let mut button_pressed = false; writeln!(serial, "Ready.").unwrap(); loop { // Read compass data and log it to the serial port. while !(imu.mag_status().unwrap().xyz_new_data() && imu.accel_status().unwrap().xyz_new_data()) {} let compass_reading = imu.magnetic_field().unwrap(); let accelerometer_reading = imu.acceleration().unwrap(); writeln!( serial, "{},{},{}\t{},{},{}", compass_reading.x_nt(), compass_reading.y_nt(), compass_reading.z_nt(), accelerometer_reading.x_mg(), accelerometer_reading.y_mg(), accelerometer_reading.z_mg(), ) .unwrap(); let mut image = [[0; 5]; 5]; let (x, y) = match mode { Mode::Compass => ( scale(-compass_reading.x_nt(), -COMPASS_SCALE, COMPASS_SCALE, 0, 4) as usize, scale(compass_reading.y_nt(), -COMPASS_SCALE, COMPASS_SCALE, 0, 4) as usize, ), Mode::Accelerometer => ( scale( accelerometer_reading.x_mg(), -ACCELEROMETER_SCALE, ACCELEROMETER_SCALE, 0, 4, ) as usize, scale( -accelerometer_reading.y_mg(), -ACCELEROMETER_SCALE, ACCELEROMETER_SCALE, 0, 4, ) as usize, ), }; image[y][x] = 255; display.show(&mut timer, image, 100); // If button A is pressed, switch to the next mode and briefly blink all LEDs // on. if board.buttons.button_a.is_low().unwrap() { if !button_pressed { mode = mode.next(); display.show(&mut timer, [[255; 5]; 5], 200); } button_pressed = true; } else { button_pressed = false; } } } #[derive(Copy, Clone, Debug, Eq, PartialEq)] enum Mode { Compass, Accelerometer, } impl Mode { fn next(self) -> Self { match self { Self::Compass => Self::Accelerometer, Self::Accelerometer => Self::Compass, } } } fn scale(value: i32, min_in: i32, max_in: i32, min_out: i32, max_out: i32) -> i32 { let range_in = max_in - min_in; let range_out = max_out - min_out; let scaled = min_out + range_out * (value - min_in) / range_in; scaled.clamp(min_out, max_out) }
ã¢ããªã±ãŒã·ã§ã³ããã»ããµ
ãããŸã§ã¯ãArm Cortex-M ã·ãªãŒãºã®ãããªãã€ã¯ãã³ã³ãããŒã©ã«ã€ããŠèª¬æããŠããŸããã ãããã¯éåžžããªãœãŒã¹ãéåžžã«éãããå°èŠæš¡ãªã·ã¹ãã ã§ãã
ããå€ãã®ãªãœãŒã¹ãæã€å€§èŠæš¡ãªã·ã¹ãã ã¯ãäžè¬ã«ã¢ããªã±ãŒã·ã§ã³ããã»ããµãšåŒã°ãã ARM Cortex-A ã Intel Atom ã®ãããªããã»ããµãäžå¿ã«æ§æãããŠããŸãã
ç°¡åã®ãããããã§ã¯ QEMU ã® aarch64 âvirtâ ããŒãã ããæ±ããŸãã
- 倧ãŸãã«èšãã°ããã€ã¯ãã³ã³ãããŒã©ã«ã¯ MMU ãè€æ°ã®ç¹æš©ã¬ãã« ïŒArm CPU ã§ã¯äŸå€ã¬ãã«ãx86 ã§ã¯ãªã³ã°ïŒããããŸããã
- ã¢ããªã±ãŒã·ã§ã³ããã»ããµã¯ããå€ãã®ãªãœãŒã¹ãåããŠãããèµ·åæã«å¯Ÿè±¡ã¢ããªã±ãŒã·ã§ã³ãçŽæ¥å®è¡ããã®ã§ã¯ãªãã OS ãå®è¡ããããšããããããŸãã
- QEMU ã¯ãåã¢ãŒããã¯ãã£åãã«ããŸããŸãªãã·ã³ãããŒãã¢ãã«ã®ãšãã¥ã¬ãŒã·ã§ã³ããµããŒãããŠããŸãã âvirtâ ããŒãã¯ç¹å®ã®å®æ©ããŒããŠã§ã¢ã«å¯Ÿå¿ãããã®ã§ã¯ãªããçŽç²ã«ä»®æ³ãã·ã³åãã«èšèšãããŠããŸãã
- ãã®ããŒãã«ã€ããŠããOS ãæžããŠãããã®ããã«ãåŒãç¶ããã¢ã¡ã¿ã«ãšããŠæ±ããŸãã
Rust ãå§ããæºå
Rust ã³ãŒãã®å®è¡ãéå§ããåã«ãããã€ãåæåãè¡ãå¿ èŠããããŸãã
/**
* This is a generic entry point for an image. It carries out the
* operations required to prepare the loaded image to be run.
* Specifically, it
*
* - sets up the MMU with an identity map of virtual to physical
* addresses, and enables caching
* - enables floating point
* - zeroes the bss section using registers x25 and above
* - prepares the stack, pointing to a section within the image
* - sets up the exception vector
* - branches to the Rust `main` function
*
* It preserves x0-x3 for the Rust entry point, as these may contain
* boot parameters.
*/
.section .init.entry, "ax"
.global entry
entry:
/*
* Load and apply the memory management configuration, ready to
* enable MMU and caches.
*/
adrp x30, idmap
msr ttbr0_el1, x30
mov_i x30, .Lmairval
msr mair_el1, x30
mov_i x30, .Ltcrval
/* Copy the supported PA range into TCR_EL1.IPS. */
mrs x29, id_aa64mmfr0_el1
bfi x30, x29, #32, #4
msr tcr_el1, x30
mov_i x30, .Lsctlrval
/*
* Ensure everything before this point has completed, then
* invalidate any potentially stale local TLB entries before they
* start being used.
*/
isb
tlbi vmalle1
ic iallu
dsb nsh
isb
/*
* Configure sctlr_el1 to enable MMU and cache and don't proceed
* until this has completed.
*/
msr sctlr_el1, x30
isb
/* Disable trapping floating point access in EL1. */
mrs x30, cpacr_el1
orr x30, x30, #(0x3 << 20)
msr cpacr_el1, x30
isb
/* Zero out the bss section. */
adr_l x29, bss_begin
adr_l x30, bss_end
0: cmp x29, x30
b.hs 1f
stp xzr, xzr, [x29], #16
b 0b
1: /* Prepare the stack. */
adr_l x30, boot_stack_end
mov sp, x30
/* Set up exception vector. */
adr x30, vector_table_el1
msr vbar_el1, x30
/* Call into Rust code. */
bl main
/* Loop forever waiting for interrupts. */
2: wfi
b 2b
ãã®ã³ãŒã㯠src/bare-metal/aps/examples/src/entry.S ã«ãããŸããããã詳现㫠çè§£ããå¿
èŠã¯ãããŸããããèŠç¹ã¯ãRust ãã·ã¹ãã ã«æåŸ
ããæ¡ä»¶ãæºããããã«ã äœããã®äœã¬ãã«ãªã»ããã¢ãããå¿
èŠã ãšããããšã§ãã
- ãã㯠C ã®å Žåãšåãã§ããã€ãŸããããã»ããµç¶æ
ãåæåããBSS ããŒãã¯ãªã¢ãã ã¹ã¿ãã¯ãã€ã³ã¿ãèšå®ããŸãã
- BSSïŒæŽå²çãªçç±ã«ããåç§°ã§ãblock starting symbolïŒã¯ã ãŒãã§åæåãããéçã«ç¢ºä¿ããã倿°ãå«ããªããžã§ã¯ããã¡ã€ã«ã®äžéšã§ãã ãããã¯ãŒãã«é åã䜿ã£ãŠç¡é§ã«ããªããããã€ã¡ãŒãžã«ã¯å«ãŸããŸããã ã³ã³ãã€ã©ã¯ãããŒããŒããããããŒãã¯ãªã¢ããŠãããããšãåæã«ããŠããŸãã
- ã¡ã¢ãªãã©ã®ããã«åæåãããã€ã¡ãŒãžãã©ã®ããã«ããŒãããããã«ãã£ãŠã¯ãBSS 㯠ãã§ã«ãŒãã¯ãªã¢ãããŠããå ŽåããããŸããã確å®ãæãããã«ãã¡ãã§ãŒãã¯ãªã¢ããŸãã
- ã¡ã¢ãªã®èªã¿æžããè¡ãåã«ãMMU ãšãã£ãã·ã¥ãæå¹ã«ããå¿
èŠããããŸããããããªããšã 次ã®åé¡ãèµ·ãããŸãã
- éã¢ã©ã€ã³ã¢ã¯ã»ã¹ã§ãã©ãŒã«ããçºçããŸããRust ã³ãŒãã¯ãã³ã³ãã€ã©ã éã¢ã©ã€ã³ã¢ã¯ã»ã¹ãçæããªããã
+strict-alignãèšå®ãããaarch64-unknown-noneã¿ãŒã²ããåãã«ãã«ãããŠããããããã®ã±ãŒã¹ã§ã¯ åé¡ãªãã¯ãã§ãããäžè¬ã«ã¯å¿ ããããããšã¯éããŸããã - VM äžã§åäœããŠããå Žåããã£ãã·ã¥ã³ããŒã¬ã³ã·ã®åé¡ã«ã€ãªããå¯èœæ§ããããŸãã åé¡ã¯ãVM ã¯ãã£ãã·ã¥ãç¡å¹ã«ããç¶æ ã§ã¡ã¢ãªã«çŽæ¥ã¢ã¯ã»ã¹ããŠããäžæ¹ã§ã ãã¹ãã¯åãã¡ã¢ãªã«å¯Ÿãããã£ãã·ã¥å¯èœãªå¥åãæã£ãŠããããšã§ãããã¹ãã æç€ºçã«ãã®ã¡ã¢ãªãžã¢ã¯ã»ã¹ããªããŠããææ©çã¢ã¯ã»ã¹ã«ãã£ãŠãã£ãã·ã¥ãã£ã«ã çºçãããã®åŸãã£ãã·ã¥ãã¯ãªãŒã³ãããã VM ããã£ãã·ã¥ãæå¹ã«ããããããšã ã©ã¡ããäžæ¹ã®å€æŽã倱ãããŠããŸããŸããïŒãã£ãã·ã¥ã¯ VA ã IPA ã§ã¯ãªãã ç©çã¢ãã¬ã¹ãããŒã«ããŠããŸããïŒ
- éã¢ã©ã€ã³ã¢ã¯ã»ã¹ã§ãã©ãŒã«ããçºçããŸããRust ã³ãŒãã¯ãã³ã³ãã€ã©ã éã¢ã©ã€ã³ã¢ã¯ã»ã¹ãçæããªããã
- åçŽåã®ãããå
é ã® 1 GiB ã®ã¢ãã¬ã¹ç©ºéãããã€ã¹çšã«ããã®æ¬¡ã® 1 GiB ã DRAM çšã«ã ããã«ãã®äžäœã®å¥ã® 1 GiB ã远å ã®ããã€ã¹çšã«æçããããããããŒãã³ãŒãããã ããŒãžããŒãã«ïŒ
idmap.Sãåç §ïŒããã®ãŸãŸäœ¿çšããŸãããã㯠QEMU ã䜿çšãã ã¡ã¢ãªã¬ã€ã¢ãŠããšäžèŽããŠããŸãã - äŸå€ãã¯ã¿ïŒ
vbar_el1ïŒãèšå®ããŸããããã«ã€ããŠã¯åŸã§ããå°ã詳ããèŠãŸãã - ãã®ååŸã®ãã¹ãŠã®äŸã§ã¯ãäŸå€ã¬ãã« 1ïŒEL1ïŒã§å®è¡ããããšãåæãšããŠããŸãã å¥ã®äŸå€ã¬ãã«ã§å®è¡ããå¿
èŠãããå Žåã¯ãããã«å¿ããŠ
entry.Sã倿Žããå¿ èŠããããŸãã
ã€ã³ã©ã€ã³ã¢ã»ã³ããª
Rust ã®ã³ãŒãã§ã¯å®çŸã§ããªãããšãè¡ãããã«ãã¢ã»ã³ããªã䜿ãå¿ èŠã ããå ŽåããããŸããããšãã°ãã·ã¹ãã ã®é»æºãåããããã¡ãŒã ãŠã§ã¢ã« äŒããããã« HVCïŒãã€ããŒãã€ã¶ãŒåŒã³åºãïŒãè¡ãå Žåã§ã:
// Copyright 2023 Google LLC // SPDX-License-Identifier: Apache-2.0 #![no_main] #![no_std] use core::arch::asm; use core::panic::PanicInfo; mod asm; mod exceptions; const PSCI_SYSTEM_OFF: u32 = 0x84000008; // SAFETY: There is no other global function of this name. #[unsafe(no_mangle)] extern "C" fn main(_x0: u64, _x1: u64, _x2: u64, _x3: u64) { // SAFETY: this only uses the declared registers and doesn't do anything // with memory. unsafe { asm!("hvc #0", inout("w0") PSCI_SYSTEM_OFF => _, inout("w1") 0 => _, inout("w2") 0 => _, inout("w3") 0 => _, inout("w4") 0 => _, inout("w5") 0 => _, inout("w6") 0 => _, inout("w7") 0 => _, options(nomem, nostack) ); } loop {} }
ïŒå®éã«ãããè¡ãããå Žåã¯ãããããã¹ãŠã®é¢æ°ã®ã©ãããŒãæäŸããŠãã smccc ã¯ã¬ãŒãã䜿ã£ãŠãã ãããïŒ
- PSCI 㯠Arm Power State Coordination Interface ã®ããšã§ãã·ã¹ãã ã CPU ã® é»æºç¶æ ãªã©ã管çããããã®æšæºçãªé¢æ°çŸ€ã§ããå€ãã®ã·ã¹ãã ã§ã¯ã EL3 ãã¡ãŒã ãŠã§ã¢ããã€ããŒãã€ã¶ãŒã«ãã£ãŠå®è£ ãããŠããŸãã
0 => _æ§æã¯ãã€ã³ã©ã€ã³ã¢ã»ã³ããªã³ãŒããå®è¡ããåã«ã¬ãžã¹ã¿ã 0 ã§ åæåãããã®åŸã¯ãã®å 容ãç¡èŠããããšãæå³ããŸããåŒã³åºãã«ãã£ãŠ ã¬ãžã¹ã¿ã®å 容ãç Žå£ãããå¯èœæ§ããããããinã§ã¯ãªãinoutã 䜿ãå¿ èŠããããŸãã- ãã®
main颿°ã¯ãentry.Så ã®ãšã³ããªãã€ã³ãããåŒã³åºãããããã#[unsafe(no_mangle)]ãšextern "C"ã§ããå¿ èŠããããŸãã#[no_mangle]ã ãã§ãååã§ããã RFC3325 ã§ã¯ã 誀ã£ãŠäœ¿çšãããšæªå®çŸ©åäœãåŒãèµ·ããå¯èœæ§ããã屿§ã«ã¬ãã¥ã¢ãŒã® 泚æãåããããã«ããã®è¡šèšã䜿ãããŠããŸãã
_x0â_x3ã¯ã¬ãžã¹ã¿x0âx3ã®å€ã§ããããããã¯æ £äŸçã« ããŒãããŒããŒãããã€ã¹ããªãŒãžã®ãã€ã³ã¿ã®ãããªå€ãæž¡ãããã«äœ¿çšããŸãã æšæºã® aarch64 åŒã³åºãèŠçŽïŒããã¯extern "C"ã䜿çšãæå®ãããã®ã§ãïŒ ã§ã¯ã颿°ã«æž¡ãããæåã® 8 åã®åŒæ°ã«ã¬ãžã¹ã¿x0âx7ã䜿ããããããentry.Sã¯ãããã®ã¬ãžã¹ã¿ã倿Žããªãããã«ãã以å€ãç¹å¥ãªããšãè¡ã å¿ èŠã¯ãããŸãããsrc/bare-metal/aps/examplesã§make qemu_psciãå®è¡ããŠãQEMU äžã§ ãã®äŸãå®è¡ããŠãã ããã
MMIO åãã® volatile ã¡ã¢ãªã¢ã¯ã»ã¹
pointer::read_volatileãšpointer::write_volatileã䜿çšããŠãã ããã- ãããã®ã¡ãœããã§ã¢ã¯ã»ã¹ããŠããå Žæãžã®åç
§ã¯æ±ºããŠä¿æããªãã§ãã ãããRust ã¯åç
§ããã€ã§ãèªã¿åãïŒ
&mutã®å Žåã¯æžã蟌ãïŒããšããããŸãã - äžéåç
§ãäœæããã«æ§é äœã®ãã£ãŒã«ããžã®ãã€ã³ã¿ãåŸãã«ã¯
&rawãäœ¿çš ããŠãã ããã
// Copyright 2023 Google LLC
// SPDX-License-Identifier: Apache-2.0
const SOME_DEVICE_REGISTER: *mut u64 = 0x800_0000 as _;
// SAFETY: ãã®ã¢ãã¬ã¹ã«ã¯äœããã®ããã€ã¹ãããããããŠããŸãã
unsafe {
SOME_DEVICE_REGISTER.write_volatile(0xff);
SOME_DEVICE_REGISTER.write_volatile(0x80);
assert_eq!(SOME_DEVICE_REGISTER.read_volatile(), 0xaa);
}
- volatile ã¢ã¯ã»ã¹: èªã¿æžãæäœã«ã¯å¯äœçšãããåŸããããã³ã³ãã€ã©ãããŒã ãŠã§ã¢ãããããäžŠã¹æ¿ããããéè€ãããããåãé€ãããããã®ãé²ããŸãã
- ããšãã°å¯å€åç §çµç±ã§æžã蟌ã¿ã®åŸã«èªã¿åããè¡ããšãã³ã³ãã€ã©ã¯èªã¿å ã£ãå€ãçŽåã«æžã蟌ãã å€ãšåãã ãšä»®å®ããå®éã«ã¯ã¡ã¢ãªãèªãŸãªãããšããããŸãã
- ããŒããŠã§ã¢ãžã® volatile ã¢ã¯ã»ã¹çšã®æ¢åã®ã¯ã¬ãŒãã®äžã«ã¯åç §ãä¿æãã ãã®ããããŸãããããã¯éå¥å šã§ããåç §ããããšãã³ã³ãã€ã©ã¯ããã ããªãã¡ã¬ã³ã¹ããå¯èœæ§ããããŸãã
- æ§é äœãžã®ãã€ã³ã¿ãããã£ãŒã«ããžã®ãã€ã³ã¿ãååŸããã«ã¯
&rawã䜿çšããŠãã ããã - å€ãããŒãžã§ã³ã® Rust ãšã®äºææ§ã®ããã«ã代ããã«
addr_of!ãã¯ãã䜿 çšã§ããŸãã
UARTãã©ã€ããŒãæžããŠã¿ãŸããã
QEMU ã® virt ãã·ã³ã«ã¯ PL011 UART ãããã®ã§ããã®ãã©ã€ããŒãæžããŠã¿ãŸãããã
// èäœæš© 2023 Google LLC // SPDX-License-Identifier: Apache-2.0 const FLAG_REGISTER_OFFSET: usize = 0x18; const FR_BUSY: u8 = 1 << 3; const FR_TXFF: u8 = 1 << 5; /// Minimal driver for a PL011 UART. #[derive(Debug)] pub struct Uart { base_address: *mut u8, } impl Uart { /// Constructs a new instance of the UART driver for a PL011 device at the /// given base address. /// /// # Safety /// /// The given base address must point to the 8 MMIO control registers of a /// PL011 device, which must be mapped into the address space of the process /// as device memory and not have any other aliases. pub unsafe fn new(base_address: *mut u8) -> Self { Self { base_address } } /// Writes a single byte to the UART. pub fn write_byte(&self, byte: u8) { // Wait until there is room in the TX buffer. while self.read_flag_register() & FR_TXFF != 0 {} // SAFETY: We know that the base address points to the control // registers of a PL011 device which is appropriately mapped. unsafe { // Write to the TX buffer. self.base_address.write_volatile(byte); } // Wait until the UART is no longer busy. while self.read_flag_register() & FR_BUSY != 0 {} } fn read_flag_register(&self) -> u8 { // SAFETY: We know that the base address points to the control // registers of a PL011 device which is appropriately mapped. unsafe { self.base_address.add(FLAG_REGISTER_OFFSET).read_volatile() } } }
Uart::new㯠unsafe ã§ãããä»ã®ã¡ãœãã㯠safe ã§ããããšã«æ³šæããŠãã ãããããã¯ãUart::newã®åŒã³åºãåŽããã®å®å šæ§èŠä»¶ïŒã€ãŸããç¹å®ã® UART ã«å¯ŸããŠãã®ãã©ã€ããŒã®ã€ã³ã¹ã¿ã³ã¹ãåžžã« 1 ã€ããååšããããã®ã¢ãã¬ã¹ç©ºéããšã€ãªã¢ã¹ãããã®ãä»ã«ååšããªãããšïŒãæºããããšãä¿èšŒããŠããéããå¿ èŠãªäºåæ¡ä»¶ãæãç«ã€ãšä»®å®ã§ãããããåŸã§write_byteãåŒã³åºãããšã¯åžžã«å®å šã ããã§ãã- éã«ããããšãã§ããŸããïŒ
newã safe ã«ããŠwrite_byteã unsafe ã«ããïŒãããããããšwrite_byteãåŒã³åºããã¹ãŠã®ç®æã§å®å šæ§ã«ã€ããŠèããªããã°ãªããã䜿ãåæã¯å€§å¹ ã«æªããªããŸã - ããã¯ãunsafe ãªã³ãŒãã«å¯Ÿãã safe ãªã©ãããŒãæžãéã«ãããããã¿ãŒã³ã§ããã€ãŸããå¥å šæ§ã®ç«èšŒè²¬ä»»ã倿°ã®ç®æãããããå°ãªãç®æãžç§»ããšããããšã§ãã
ãã®ä»ã®ãã¬ã€ã
Debug ãã¬ã€ã㯠derive ããŸãããããã«ããã€ãã®ãã¬ã€ããå®è£
ãããšäŸ¿å©ã§ãã
// èäœæš© 2023 Google LLC // SPDX-License-Identifier: Apache-2.0 use core::fmt::{self, Write}; impl Write for Uart { fn write_str(&mut self, s: &str) -> fmt::Result { for c in s.as_bytes() { self.write_byte(*c); } Ok(()) } } // SAFETY: `Uart` just contains a pointer to device memory, which can be // accessed from any context. unsafe impl Send for Uart {}
-
Writeãå®è£ ãããšãUartåã§write!ãã¯ããšwriteln!ãã¯ãã䜿ããããã«ãªããŸãã -
Sendã¯èªåãã¬ã€ãã§ããããã€ã³ã¿ã«ã¯å®è£ ãããŠããªããããèªåçã«ã¯å®è£ ãããŸããã
䜿ã£ãŠã¿ã
ãã©ã€ãã䜿ã£ãŠã·ãªã¢ã«ã³ã³ãœãŒã«ã«æžã蟌ãå°ããªããã°ã©ã ãæžããŠã¿ãŸãããã
// èäœæš© 2025 Google LLC // SPDX-License-Identifier: Apache-2.0 #![no_main] #![no_std] mod asm; mod exceptions; mod pl011_minimal; use crate::pl011_minimal::Uart; use core::fmt::Write; use core::panic::PanicInfo; use log::error; use smccc::Hvc; use smccc::psci::system_off; /// Base address of the primary PL011 UART. const PL011_BASE_ADDRESS: *mut u8 = 0x900_0000 as _; // SAFETY: There is no other global function of this name. #[unsafe(no_mangle)] extern "C" fn main(x0: u64, x1: u64, x2: u64, x3: u64) { // SAFETY: `PL011_BASE_ADDRESS` is the base address of a PL011 device, and // nothing else accesses that address range. let mut uart = unsafe { Uart::new(PL011_BASE_ADDRESS) }; writeln!(uart, "main({x0:#x}, {x1:#x}, {x2:#x}, {x3:#x})").unwrap(); system_off::<Hvc>().unwrap(); }
- inline assembly ã®äŸãšåæ§ã«ããã®
main颿°ã¯entry.Sã®ãšã³ããªãã€ã³ãã³ãŒãããåŒã³åºãããŸãã詳现ã¯ããã¡ãã® ã¹ããŒã«ãŒããŒããåç §ããŠãã ããã src/bare-metal/aps/examplesã§make qemu_minimalãå®è¡ããŠã ãã®äŸã QEMU ã§å®è¡ããŸãã
ããè¯ãUARTãã©ã€ããŒ
PL011 ã«ã¯å®éã«ã¯ããã«å€ãã®ã¬ãžã¹ã¿ãããããããã«ã¢ã¯ã»ã¹ããããã®ãã€ã³ã¿ãæ§ç¯ããããã«ãªãã»ãããå ããæ¹æ³ã¯ããšã©ãŒãçºçãããããèªã¿ã«ãããªããŸããããã«ããã®äžéšã¯ããããã£ãŒã«ãã§ãããæ§é åãããæ¹æ³ã§ã¢ã¯ã»ã¹ã§ãããšäŸ¿å©ã§ãã
| ãªãã»ãã | ã¬ãžã¹ã¿å | ãããå¹ |
|---|---|---|
| 0x00 | DR | 12 |
| 0x04 | RSR | 4 |
| 0x18 | FR | 9 |
| 0x20 | ILPR | 8 |
| 0x24 | IBRD | 16 |
| 0x28 | FBRD | 6 |
| 0x2c | LCR_H | 8 |
| 0x30 | CR | 16 |
| 0x34 | IFLS | 6 |
| 0x38 | IMSC | 11 |
| 0x3c | RIS | 11 |
| 0x40 | MIS | 11 |
| 0x44 | ICR | 11 |
| 0x48 | DMACR | 3 |
- ç°¡æœã«ãããããçç¥ããIDã¬ãžã¹ã¿ããããŸãã
ããããã©ã°
bitflags ã¯ã¬ãŒãã¯ãããããã©ã°ãæ±ãéã«äŸ¿å©ã§ãã
// èäœæš© 2023 Google LLC // SPDX-License-Identifier: Apache-2.0 use bitflags::bitflags; bitflags! { /// Flags from the UART flag register. #[repr(transparent)] #[derive(Copy, Clone, Debug, Eq, PartialEq)] struct Flags: u16 { /// Clear to send. const CTS = 1 << 0; /// Data set ready. const DSR = 1 << 1; /// Data carrier detect. const DCD = 1 << 2; /// UART busy transmitting data. const BUSY = 1 << 3; /// Receive FIFO is empty. const RXFE = 1 << 4; /// Transmit FIFO is full. const TXFF = 1 << 5; /// Receive FIFO is full. const RXFF = 1 << 6; /// Transmit FIFO is empty. const TXFE = 1 << 7; /// Ring indicator. const RI = 1 << 8; } }
bitflags!ãã¯ãã¯ãstruct Flags(u16)ã®ãã㪠newtype ãäœæãã ãã©ã°ã®ååŸãšèšå®ãè¡ãããã®å€æ°ã®ã¡ãœããå®è£ ã䜵ããŠçæããŸãã
è€æ°ã®ã¬ãžã¹ã¿
æ§é äœã䜿ã£ãŠãUART ã®ã¬ãžã¹ã¿ã®ã¡ã¢ãªã¬ã€ã¢ãŠãã衚çŸã§ããŸãã
// Copyright 2023 Google LLC // SPDX-License-Identifier: Apache-2.0 #[repr(C, align(4))] pub struct Registers { dr: u16, _reserved0: [u8; 2], rsr: ReceiveStatus, _reserved1: [u8; 19], fr: Flags, _reserved2: [u8; 6], ilpr: u8, _reserved3: [u8; 3], ibrd: u16, _reserved4: [u8; 2], fbrd: u8, _reserved5: [u8; 3], lcr_h: u8, _reserved6: [u8; 3], cr: u16, _reserved7: [u8; 3], ifls: u8, _reserved8: [u8; 3], imsc: u16, _reserved9: [u8; 2], ris: u16, _reserved10: [u8; 2], mis: u16, _reserved11: [u8; 2], icr: u16, _reserved12: [u8; 2], dmacr: u8, _reserved13: [u8; 3], }
#[repr(C)]ã¯ãC ãšåãã«ãŒã«ã«åŸã£ãŠãæ§é äœã®ãã£ãŒã«ããé çªã«é 眮ãããã ã³ã³ãã€ã©ã«æç€ºããŸããããã¯ãæ§é äœã®ã¬ã€ã¢ãŠããäºæž¬å¯èœã«ããããã« å¿ èŠã§ããRust ã®ããã©ã«ã衚çŸã§ã¯ãã³ã³ãã€ã©ã¯ïŒãšãããïŒ ãã£ãŒã«ããèªç±ã«äžŠã¹æ¿ããããšãã§ããããã§ãã
ãã©ã€ã
ããã§ã¯ããã©ã€ãã§æ°ãã Registers æ§é äœã䜿ããŸãããã
// Copyright 2023 Google LLC // SPDX-License-Identifier: Apache-2.0 /// Driver for a PL011 UART. #[derive(Debug)] pub struct Uart { registers: *mut Registers, } impl Uart { /// Constructs a new instance of the UART driver for a PL011 device with the /// given set of registers. /// /// # Safety /// /// The given pointer must point to the 8 MMIO control registers of a PL011 /// device, which must be mapped into the address space of the process as /// device memory and not have any other aliases. pub unsafe fn new(registers: *mut Registers) -> Self { Self { registers } } /// Writes a single byte to the UART. pub fn write_byte(&mut self, byte: u8) { // Wait until there is room in the TX buffer. while self.read_flag_register().contains(Flags::TXFF) {} // SAFETY: We know that self.registers points to the control registers // of a PL011 device which is appropriately mapped. unsafe { // Write to the TX buffer. (&raw mut (*self.registers).dr).write_volatile(byte.into()); } // Wait until the UART is no longer busy. while self.read_flag_register().contains(Flags::BUSY) {} } /// Reads and returns a pending byte, or `None` if nothing has been /// received. pub fn read_byte(&mut self) -> Option<u8> { if self.read_flag_register().contains(Flags::RXFE) { None } else { // SAFETY: We know that self.registers points to the control // registers of a PL011 device which is appropriately mapped. let data = unsafe { (&raw const (*self.registers).dr).read_volatile() }; // TODO: Check for error conditions in bits 8-11. Some(data as u8) } } fn read_flag_register(&self) -> Flags { // SAFETY: We know that self.registers points to the control registers // of a PL011 device which is appropriately mapped. unsafe { (&raw const (*self.registers).fr).read_volatile() } } }
- åã
ã®ãã£ãŒã«ããžã®ãã€ã³ã¿ãååŸããããã«ãäžéã®åç
§ãäœæããã«
&raw const/&raw mutã䜿ã£ãŠããç¹ã«æ³šç®ããŠãã ãããäžéã®åç §ãäœæãããšãäžå¥å šã«ãªããŸãã - ãã®äŸã¯ã次ã«åºãŠãã
safe-mmioã®äŸãšéåžžã«ãã䌌ãŠãããããã¹ã©ã€ãã«ã¯å«ãŸããŠããŸãããå¿ èŠã§ããã°ãsrc/bare-metal/aps/examplesé äžã§make qemuãå®è¡ã㊠QEMU äžã§åãããŸãã
safe-mmio
safe-mmio ã¯ã¬ãŒãã¯ãã¬ãžã¹ã¿ãå®å
šã«èªã¿æžãã§ããããã«ã©ããããåãæäŸããŸãã
| èªã¿åãäžå¯ | èªã¿åãã«å¯äœçšããªã | èªã¿åãã«å¯äœçšããã | |
|---|---|---|---|
| æžã蟌ã¿äžå¯ | ReadPure | ReadOnly | |
| æžã蟌ã¿å¯ | WriteOnly | ReadPureWrite | ReadWrite |
// Copyright 2025 Google LLC // SPDX-License-Identifier: Apache-2.0 use safe_mmio::fields::{ReadPure, ReadPureWrite, ReadWrite, WriteOnly}; #[repr(C, align(4))] pub struct Registers { dr: ReadWrite<u16>, _reserved0: [u8; 2], rsr: ReadPure<ReceiveStatus>, _reserved1: [u8; 19], fr: ReadPure<Flags>, _reserved2: [u8; 6], ilpr: ReadPureWrite<u8>, _reserved3: [u8; 3], ibrd: ReadPureWrite<u16>, _reserved4: [u8; 2], fbrd: ReadPureWrite<u8>, _reserved5: [u8; 3], lcr_h: ReadPureWrite<u8>, _reserved6: [u8; 3], cr: ReadPureWrite<u16>, _reserved7: [u8; 3], ifls: ReadPureWrite<u8>, _reserved8: [u8; 3], imsc: ReadPureWrite<u16>, _reserved9: [u8; 2], ris: ReadPure<u16>, _reserved10: [u8; 2], mis: ReadPure<u16>, _reserved11: [u8; 2], icr: WriteOnly<u16>, _reserved12: [u8; 2], dmacr: ReadPureWrite<u8>, _reserved13: [u8; 3], }
drã®èªã¿åãã«ã¯å¯äœçšããããŸããåä¿¡ FIFO ãã 1 ãã€ãåãåºããŸããrsrïŒããã³ä»ã®ã¬ãžã¹ã¿ïŒã®èªã¿åãã«ã¯å¯äœçšããããŸãããããã¯ãpureããªèªã¿åãã§ãã
- MMIO æäœã«å¯Ÿããå®å
šãªæœè±¡åãæäŸããã¯ã¬ãŒãã¯ããã€ããããŸããã
safe-mmioã¯ã¬ãŒããæšå¥šããŸãã ReadPureãšReadOnlyã®éãïŒåæ§ã«ReadPureWriteãšReadWriteã®éãïŒã¯ãã¬ãžã¹ã¿ã®èªã¿åãã«ããã€ã¹ã®ç¶æ ãå€åãããå¯äœçšãããåŸããã©ããã§ããããšãã°ãããŒã¿ã¬ãžã¹ã¿ãèªã¿åããšåä¿¡ FIFO ãã 1 ãã€ãåãåºãããŸããReadPureã¯ãèªã¿åãã«å¯äœçšããªããçŽç²ã«ããŒã¿ãèªã¿åãã ãã§ããããšãæå³ããŸãã
ãã©ã€ã
ã§ã¯ããã©ã€ãã§æ°ãã Registers æ§é äœã䜿ã£ãŠã¿ãŸãããã
// èäœæš© 2025 Google LLC // SPDX-License-Identifier: Apache-2.0 use safe_mmio::{UniqueMmioPointer, field, field_shared}; /// Driver for a PL011 UART. #[derive(Debug)] pub struct Uart<'a> { registers: UniqueMmioPointer<'a, Registers>, } impl<'a> Uart<'a> { /// Constructs a new instance of the UART driver for a PL011 device with the /// given set of registers. pub fn new(registers: UniqueMmioPointer<'a, Registers>) -> Self { Self { registers } } /// Writes a single byte to the UART. pub fn write_byte(&mut self, byte: u8) { // Wait until there is room in the TX buffer. while self.read_flag_register().contains(Flags::TXFF) {} // Write to the TX buffer. field!(self.registers, dr).write(byte.into()); // Wait until the UART is no longer busy. while self.read_flag_register().contains(Flags::BUSY) {} } /// Reads and returns a pending byte, or `None` if nothing has been /// received. pub fn read_byte(&mut self) -> Option<u8> { if self.read_flag_register().contains(Flags::RXFE) { None } else { let data = field!(self.registers, dr).read(); // TODO: Check for error conditions in bits 8-11. Some(data as u8) } } fn read_flag_register(&self) -> Flags { field_shared!(self.registers, fr).read() } }
- ãã®ãã©ã€ãã§ã¯ããã¯ã unsafe ã³ãŒãã¯å¿ èŠãããŸããïŒ
UniqueMmioPointerã¯ãMMIO ããã€ã¹ãŸãã¯ã¬ãžã¹ã¿ãžã®çãã€ã³ã¿ãã©ãããããã®ã§ããUniqueMmioPointer::newã®åŒã³åºãå ã¯ããããæå®ãããã©ã€ãã¿ã€ã ã®éã«æå¹ã§äžæã§ããããšãä¿èšŒããããããã£ãŒã«ããå®å šã«èªã¿æžãããã¡ãœãããæäŸã§ããŸããUart::newã¯çŸåšã§ã¯ safe ã§ããã代ããã«UniqueMmioPointer::newã unsafe ã§ããããšã«æ³šæããŠãã ããã- ãããã® MMIO ã¢ã¯ã»ã¹ã¯äžè¬ã«
read_volatileãšwrite_volatileã®ã©ãããŒã§ãããaarch64 ã§ã¯ä»£ããã«ã¢ã»ã³ããªã§å®è£ ãããŠããŸããããã¯ãã³ã³ãã€ã©ã MMIO ä»®æ³åã劚ããåœä»€ãåºåããŠããŸããã°ãåé¿ããããã§ãã field!ããã³field_shared!ãã¯ãã¯å éšã§&raw mutãš&raw constã䜿çšããŠãäžéåç §ãäœæããã«åã ã®ãã£ãŒã«ããžã®ãã€ã³ã¿ãååŸããŸããäžéåç §ãäœæãããšäžå¥å šã«ãªãããã§ããfield!ã¯UniqueMmioPointerãžã®å¯å€åç §ãå¿ èŠãšããå¯äœçšã䌎ãèªã¿åããšæžã蟌ã¿ãèš±å¯ããUniqueMmioPointerãè¿ããŸããfield_shared!ã¯ãUniqueMmioPointerãŸãã¯SharedMmioPointerã®ãããããžã®å ±æåç §ã§åäœããŸããããã¯ãçŽç²ãªèªã¿åãã®ã¿ãèš±å¯ããSharedMmioPointerãè¿ããŸãã
䜿ã£ãŠã¿ã
ãã©ã€ãã䜿ã£ãŠã·ãªã¢ã«ã³ã³ãœãŒã«ã«æžã蟌ã¿ãåä¿¡ãããã€ãããšã³ãŒããå°ããªããã°ã©ã ãæžããŠã¿ãŸãããã
// Copyright 2025 Google LLC // SPDX-License-Identifier: Apache-2.0 #![no_main] #![no_std] mod asm; mod exceptions; mod pl011; use crate::pl011::Uart; use core::fmt::Write; use core::panic::PanicInfo; use core::ptr::NonNull; use log::error; use safe_mmio::UniqueMmioPointer; use smccc::Hvc; use smccc::psci::system_off; /// Base address of the primary PL011 UART. const PL011_BASE_ADDRESS: NonNull<pl011::Registers> = NonNull::new(0x900_0000 as _).unwrap(); // SAFETY: There is no other global function of this name. #[unsafe(no_mangle)] extern "C" fn main(x0: u64, x1: u64, x2: u64, x3: u64) { // SAFETY: `PL011_BASE_ADDRESS` is the base address of a PL011 device, and // nothing else accesses that address range. let mut uart = Uart::new(unsafe { UniqueMmioPointer::new(PL011_BASE_ADDRESS) }); writeln!(uart, "main({x0:#x}, {x1:#x}, {x2:#x}, {x3:#x})").unwrap(); loop { if let Some(byte) = uart.read_byte() { uart.write_byte(byte); match byte { b'\r' => uart.write_byte(b'\n'), b'q' => break, _ => continue, } } } writeln!(uart, "\n\nBye!").unwrap(); system_off::<Hvc>().unwrap(); }
src/bare-metal/aps/examplesã§make qemu_safemmioãå®è¡ããŠããã®äŸã QEMU äžã§åãããŸãã
ãã®ã³ã°
log ã¯ã¬ãŒãã®ãã®ã³ã°ãã¯ãã䜿ãããšäŸ¿å©ã§ãã ãã㯠Log ãã¬ã€ããå®è£
ããããšã§å®çŸã§ããŸãã
// èäœæš© 2023 Google LLC // SPDX-License-Identifier: Apache-2.0 use crate::pl011::Uart; use core::fmt::Write; use log::{LevelFilter, Log, Metadata, Record, SetLoggerError}; use spin::mutex::SpinMutex; static LOGGER: Logger = Logger { uart: SpinMutex::new(None) }; struct Logger { uart: SpinMutex<Option<Uart<'static>>>, } impl Log for Logger { fn enabled(&self, _metadata: &Metadata) -> bool { true } fn log(&self, record: &Record) { writeln!( self.uart.lock().as_mut().unwrap(), "[{}] {}", record.level(), record.args() ) .unwrap(); } fn flush(&self) {} } /// Initialises UART logger. pub fn init( uart: Uart<'static>, max_level: LevelFilter, ) -> Result<(), SetLoggerError> { LOGGER.uart.lock().replace(uart); log::set_logger(&LOGGER)?; log::set_max_level(max_level); Ok(()) }
logå ã®æåã® unwrap ã¯ãset_loggerãåŒã³åºãåã«LOGGERãåæåããŠãããã æåããŸãã2 ã€ç®ã¯ãUart::write_strãåžžã«Okãè¿ããã æåããŸãã
䜿ã
䜿çšããåã«ãã¬ãŒãåæåããå¿ èŠããããŸãã
// Copyright 2023 Google LLC // SPDX-License-Identifier: Apache-2.0 #![no_main] #![no_std] mod asm; mod exceptions; mod logger; mod pl011; use crate::pl011::Uart; use core::panic::PanicInfo; use core::ptr::NonNull; use log::{LevelFilter, error, info}; use safe_mmio::UniqueMmioPointer; use smccc::Hvc; use smccc::psci::system_off; /// Base address of the primary PL011 UART. const PL011_BASE_ADDRESS: NonNull<pl011::Registers> = NonNull::new(0x900_0000 as _).unwrap(); // SAFETY: There is no other global function of this name. #[unsafe(no_mangle)] extern "C" fn main(x0: u64, x1: u64, x2: u64, x3: u64) { // SAFETY: `PL011_BASE_ADDRESS` is the base address of a PL011 device, and // nothing else accesses that address range. let uart = unsafe { Uart::new(UniqueMmioPointer::new(PL011_BASE_ADDRESS)) }; logger::init(uart, LevelFilter::Trace).unwrap(); info!("main({x0:#x}, {x1:#x}, {x2:#x}, {x3:#x})"); assert_eq!(x1, 42); system_off::<Hvc>().unwrap(); } #[panic_handler] fn panic(info: &PanicInfo) -> ! { error!("{info}"); system_off::<Hvc>().unwrap(); loop {} }
- panic ãã³ãã©ã panic ã®è©³çްããã°ã«èšé²ã§ããããã«ãªã£ãããšã«æ³šæããŠãã ããã
src/bare-metal/aps/examplesã§make qemu_loggerãå®è¡ããŠã ãã®äŸã QEMU ã§å®è¡ããŠãã ããã
äŸå€
AArch64 ã¯ã4 ã€ã®ç¶æ ïŒSP0 ã䜿çšããçŸåšã® ELãSPx ã䜿çšããçŸåšã® ELãAArch64 ã䜿çšããäžäœ ELãAArch32 ã䜿çšããäžäœ ELïŒããã® 4 çš®é¡ã®äŸå€ïŒåæãIRQãFIQãSErrorïŒã«å¯ŸããŠã16 åã®ãšã³ããªãæã€äŸå€ãã¯ã¿ãŒããŒãã«ãå®çŸ©ããŠããŸããRust ã³ãŒããåŒã³åºãåã«æ®çºæ§ã¬ãžã¹ã¿ãã¹ã¿ãã¯ã«ä¿åããããããããã¢ã»ã³ããªã§å®è£ ããŸãã
// Copyright 2023 Google LLC // SPDX-License-Identifier: Apache-2.0 use log::error; use smccc::Hvc; use smccc::psci::system_off; // SAFETY: There is no other global function of this name. #[unsafe(no_mangle)] extern "C" fn sync_current(_elr: u64, _spsr: u64) { error!("sync_current"); system_off::<Hvc>().unwrap(); } // SAFETY: There is no other global function of this name. #[unsafe(no_mangle)] extern "C" fn irq_current(_elr: u64, _spsr: u64) { error!("irq_current"); system_off::<Hvc>().unwrap(); } // SAFETY: There is no other global function of this name. #[unsafe(no_mangle)] extern "C" fn fiq_current(_elr: u64, _spsr: u64) { error!("fiq_current"); system_off::<Hvc>().unwrap(); } // SAFETY: There is no other global function of this name. #[unsafe(no_mangle)] extern "C" fn serror_current(_elr: u64, _spsr: u64) { error!("serror_current"); system_off::<Hvc>().unwrap(); } // SAFETY: There is no other global function of this name. #[unsafe(no_mangle)] extern "C" fn sync_lower(_elr: u64, _spsr: u64) { error!("sync_lower"); system_off::<Hvc>().unwrap(); } // SAFETY: There is no other global function of this name. #[unsafe(no_mangle)] extern "C" fn irq_lower(_elr: u64, _spsr: u64) { error!("irq_lower"); system_off::<Hvc>().unwrap(); } // SAFETY: There is no other global function of this name. #[unsafe(no_mangle)] extern "C" fn fiq_lower(_elr: u64, _spsr: u64) { error!("fiq_lower"); system_off::<Hvc>().unwrap(); } // SAFETY: There is no other global function of this name. #[unsafe(no_mangle)] extern "C" fn serror_lower(_elr: u64, _spsr: u64) { error!("serror_lower"); system_off::<Hvc>().unwrap(); }
- EL ã¯äŸå€ã¬ãã«ã§ãããã®ååŸã®äŸã¯ãã¹ãŠ EL1 ã§å®è¡ãããŸãã
- ç°¡åã®ãããçŸåšã® EL ã®äŸå€ã§ã¯ SP0 ãš SPx ãåºå¥ãããäžäœ EL ã®äŸå€ã§ã¯ AArch32 ãš AArch64 ãåºå¥ããŸããã
- ãã®äŸã§ã¯ãããããå®éã«çºçããããšã¯æ³å®ããŠããªããããäŸå€ããã°ã«èšé²ããŠé»æºãèœãšãã ãã§ãã
- äŸå€ãã³ãã©ãšã¡ã€ã³ã®å®è¡ã³ã³ããã¹ãã¯ãã ãããå¥ã
ã®ã¹ã¬ããã®ãããªãã®ãšèããããŸãã
SendãšSyncããã¹ã¬ããã®å Žåãšåãããã«ããããã®éã§äœãå ±æã§ããããå¶åŸ¡ããŸããããšãã°ãäŸå€ãã³ãã©ãšããã°ã©ã ã®æ®ãã®éšåã®éã§äœããã®å€ãå ±æãããå Žåããã®å€ãSendã§ã¯ãããSyncã§ã¯ãªããªããMutexã®ãããªãã®ã§ã©ããããŠstaticã«çœ®ãå¿ èŠããããŸãã
äŸå€ãã¯ã¿ãŒã®ã¢ã»ã³ããªã³ãŒã:
/**
* Saves the volatile registers onto the stack. This currently takes
* 14 instructions, so it can be used in exception handlers with 18
* instructions left.
*
* On return, x0 and x1 are initialised to elr_el2 and spsr_el2
* respectively, which can be used as the first and second arguments
* of a subsequent call.
*/
.macro save_volatile_to_stack
/* Reserve stack space and save registers x0-x18, x29 & x30. */
stp x0, x1, [sp, #-(8 * 24)]!
stp x2, x3, [sp, #8 * 2]
stp x4, x5, [sp, #8 * 4]
stp x6, x7, [sp, #8 * 6]
stp x8, x9, [sp, #8 * 8]
stp x10, x11, [sp, #8 * 10]
stp x12, x13, [sp, #8 * 12]
stp x14, x15, [sp, #8 * 14]
stp x16, x17, [sp, #8 * 16]
str x18, [sp, #8 * 18]
stp x29, x30, [sp, #8 * 20]
/*
* Save elr_el1 & spsr_el1. This such that we can take nested
* exception and still be able to unwind.
*/
mrs x0, elr_el1
mrs x1, spsr_el1
stp x0, x1, [sp, #8 * 22]
.endm
/**
* Restores the volatile registers from the stack. This currently
* takes 14 instructions, so it can be used in exception handlers
* while still leaving 18 instructions left; if paired with
* save_volatile_to_stack, there are 4 instructions to spare.
*/
.macro restore_volatile_from_stack
/* Restore registers x2-x18, x29 & x30. */
ldp x2, x3, [sp, #8 * 2]
ldp x4, x5, [sp, #8 * 4]
ldp x6, x7, [sp, #8 * 6]
ldp x8, x9, [sp, #8 * 8]
ldp x10, x11, [sp, #8 * 10]
ldp x12, x13, [sp, #8 * 12]
ldp x14, x15, [sp, #8 * 14]
ldp x16, x17, [sp, #8 * 16]
ldr x18, [sp, #8 * 18]
ldp x29, x30, [sp, #8 * 20]
/*
* Restore registers elr_el1 & spsr_el1, using x0 & x1 as scratch.
*/
ldp x0, x1, [sp, #8 * 22]
msr elr_el1, x0
msr spsr_el1, x1
/* Restore x0 & x1, and release stack space. */
ldp x0, x1, [sp], #8 * 24
.endm
/**
* This is a generic handler for exceptions taken at the current EL. It saves
* volatile registers to the stack, calls the Rust handler, restores volatile
* registers, then returns.
*
* This also works for exceptions taken from lower ELs, if we don't care about
* non-volatile registers.
*
* Saving state and jumping to the Rust handler takes 15 instructions, and
* restoring and returning also takes 15 instructions, so we can fit the whole
* handler in 30 instructions, under the limit of 32.
*/
.macro current_exception handler:req
save_volatile_to_stack
bl \handler
restore_volatile_from_stack
eret
.endm
.section .text.vector_table_el1, "ax"
.global vector_table_el1
.balign 0x800
vector_table_el1:
sync_cur_sp0:
current_exception sync_current
.balign 0x80
irq_cur_sp0:
current_exception irq_current
.balign 0x80
fiq_cur_sp0:
current_exception fiq_current
.balign 0x80
serr_cur_sp0:
current_exception serror_current
.balign 0x80
sync_cur_spx:
current_exception sync_current
.balign 0x80
irq_cur_spx:
current_exception irq_current
.balign 0x80
fiq_cur_spx:
current_exception fiq_current
.balign 0x80
serr_cur_spx:
current_exception serror_current
.balign 0x80
sync_lower_64:
current_exception sync_lower
.balign 0x80
irq_lower_64:
current_exception irq_lower
.balign 0x80
fiq_lower_64:
current_exception fiq_lower
.balign 0x80
serr_lower_64:
current_exception serror_lower
.balign 0x80
sync_lower_32:
current_exception sync_lower
.balign 0x80
irq_lower_32:
current_exception irq_lower
.balign 0x80
fiq_lower_32:
current_exception fiq_lower
.balign 0x80
serr_lower_32:
current_exception serror_lower
aarch64-rt
aarch64-rt crate ã¯ã以åã«å®è£
ããã¢ã»ã³ããªã®ãšã³ããªãã€ã³ããšäŸå€ãã¯ã¿ãŒãæäŸããŸããå¿
èŠãªã®ã¯ãentry! ãã¯ãã§ main 颿°ãããŒã¯ããããšã ãã§ãã
ãŸãã以åã®ããã«ã¢ã»ã³ããªã³ãŒãã§å®çŸ©ããã®ã§ã¯ãªããRust ã§åæã®éçããŒãžããŒãã«ãå®çŸ©ã§ãã initial_pagetable! ãã¯ããæäŸããŸãã
ããã«ãç¬èªã«å®è£
ãã代ããã«ãarm-pl011-uart crate ã® UART ãã©ã€ããŒã䜿çšã§ããŸãã
// Copyright 2025 Google LLC // SPDX-License-Identifier: Apache-2.0 #![no_main] #![no_std] mod exceptions_rt; use aarch64_paging::descriptor::El1Attributes; use aarch64_rt::{InitialPagetable, entry, initial_pagetable}; use arm_pl011_uart::{PL011Registers, Uart, UniqueMmioPointer}; use core::fmt::Write; use core::panic::PanicInfo; use core::ptr::NonNull; use smccc::Hvc; use smccc::psci::system_off; /// Base address of the primary PL011 UART. const PL011_BASE_ADDRESS: NonNull<PL011Registers> = NonNull::new(0x900_0000 as _).unwrap(); /// Attributes to use for device memory in the initial identity map. const DEVICE_ATTRIBUTES: El1Attributes = El1Attributes::VALID .union(El1Attributes::ATTRIBUTE_INDEX_0) .union(El1Attributes::ACCESSED) .union(El1Attributes::UXN); /// Attributes to use for normal memory in the initial identity map. const MEMORY_ATTRIBUTES: El1Attributes = El1Attributes::VALID .union(El1Attributes::ATTRIBUTE_INDEX_1) .union(El1Attributes::INNER_SHAREABLE) .union(El1Attributes::ACCESSED) .union(El1Attributes::NON_GLOBAL); initial_pagetable!({ let mut idmap = [0; 512]; // 1 GiB of device memory. idmap[0] = DEVICE_ATTRIBUTES.bits(); // 1 GiB of normal memory. idmap[1] = MEMORY_ATTRIBUTES.bits() | 0x40000000; // Another 1 GiB of device memory starting at 256 GiB. idmap[256] = DEVICE_ATTRIBUTES.bits() | 0x4000000000; InitialPagetable(idmap) }); entry!(main); fn main(x0: u64, x1: u64, x2: u64, x3: u64) -> ! { // SAFETY: `PL011_BASE_ADDRESS` is the base address of a PL011 device, and // nothing else accesses that address range. let mut uart = unsafe { Uart::new(UniqueMmioPointer::new(PL011_BASE_ADDRESS)) }; writeln!(uart, "main({x0:#x}, {x1:#x}, {x2:#x}, {x3:#x})").unwrap(); system_off::<Hvc>().unwrap(); panic!("system_off returned"); } #[panic_handler] fn panic(_info: &PanicInfo) -> ! { system_off::<Hvc>().unwrap(); loop {} }
src/bare-metal/aps/examplesã§make qemu_rtãå®è¡ããŠããã®ãµã³ãã«ã QEMU ã§åãããŸãã
äŸå€
aarch64-rt ã¯ãäŸå€ãã³ãã©ãå®çŸ©ããããã®ãã¬ã€ããšãããããåŒã³åºã äŸå€ãã¯ã¿åãã®ã¢ã»ã³ããªã³ãŒããçæãããã¯ããæäŸããŸãã
ãã®ãã¬ã€ãã«ã¯ãåã« panic ããåã¡ãœããã®ããã©ã«ãå®è£ ãããããã çºçããªããšæ³å®ããŠããäŸå€ã®ã¡ãœããã¯çç¥ã§ããŸãã
// Copyright 2026 Google LLC // SPDX-License-Identifier: Apache-2.0 use aarch64_rt::{ExceptionHandlers, RegisterStateRef, exception_handlers}; use log::error; use smccc::Hvc; use smccc::psci::system_off; struct Handlers; impl ExceptionHandlers for Handlers { extern "C" fn sync_current(_state: RegisterStateRef) { error!("sync_current"); system_off::<Hvc>().unwrap(); } extern "C" fn irq_current(_state: RegisterStateRef) { error!("irq_current"); system_off::<Hvc>().unwrap(); } extern "C" fn fiq_current(_state: RegisterStateRef) { error!("fiq_current"); system_off::<Hvc>().unwrap(); } extern "C" fn serror_current(_state: RegisterStateRef) { error!("serror_current"); system_off::<Hvc>().unwrap(); } } exception_handlers!(Handlers);
exception_handlersãã¯ãã¯ãRust ã³ãŒããåŒã³åºãããã®äŸå€ãã¯ã¿ãå«ãglobal_asm!ãããã¯ãçæããŸããããã¯ã以å䜿çšããŠããexceptions.S㚠䌌ãŠããŸããRegisterStateRefã¯ãäŸå€ãçºçãããšãã«ã¢ã»ã³ããªã³ãŒãã«ãã£ãŠã¬ãžã¹ã¿å€ã ä¿åãããã¹ã¿ãã¯ãã¬ãŒã ãžã®åç §ãã©ããããŸããããã¯ãããšãã°äžäœ EL ããã® SMC ãŸã㯠HVC åŒã³åºãã®ãã©ã¡ãŒã¿ãåãåºããäŸå€ãã³ãã©ã®åŸ©åž°æã« 埩å ãããå€ãæŽæ°ããããã«äœ¿çšã§ããŸãã
ãã®ä»ã®ãããžã§ã¯ã
- oreboot
- ãC ã®ãªã corebootãã
- x86ãaarch64ãRISC-V ããµããŒãããŸãã
- 倿°ã®ãã©ã€ããŒãèªåã§æã€ã®ã§ã¯ãªããLinuxBoot ã«äŸåããŸãã
- Rust RaspberryPi OS ãã¥ãŒããªã¢ã«
- åæåãUART ãã©ã€ããŒãã·ã³ãã«ãªããŒãããŒããŒãJTAGãäŸå€ã¬ãã«ã äŸå€åŠçãããŒãžããŒãã«ã
- Rust ã«ããããã£ãã·ã¥ã¡ã³ããã³ã¹ãšåæåã«ã¯ããã€ã泚æç¹ããããæ¬çªã³ãŒãã® ææ¬ãšããŠãã®ãŸãŸç䌌ããã«ã¯å¿ ãããããäŸã§ã¯ãããŸããã
cargo-call-stack- æå€§ã¹ã¿ãã¯äœ¿çšéãç®åºããããã®éçè§£æã
- RaspberryPi OS ãã¥ãŒããªã¢ã«ã§ã¯ãMMU ãšãã£ãã·ã¥ã æå¹ã«ãªãåã« Rust ã³ãŒããå®è¡ããŸããããã«ããã¡ã¢ãªïŒããšãã°ã¹ã¿ãã¯ïŒãèªã¿æžããããŸãããã ããããã«ã¯ããã®ã»ãã·ã§ã³ã®åé ã§è¿°ã¹ããéæŽåã¢ã¯ã»ã¹ãšãã£ãã·ã¥ã³ããŒã¬ã³ã·ã«é¢ããåé¡ããããŸãã
圹ç«ã€ã¯ã¬ãŒã
ãã¢ã¡ã¿ã«ããã°ã©ãã³ã°ã§ããããåé¡ã解決ãããããã€ãã®ã¯ã¬ãŒããèŠãŠãããŸãã
zerocopy
zerocopy crateïŒFuchsia ç±æ¥ïŒã¯ããã€ãåãšä»ã®åã®éãå®å
šã«å€æããããã®ãã¬ã€ããšãã¯ããæäŸããŸãã
// èäœæš© 2023 Google LLC // SPDX-License-Identifier: Apache-2.0 use zerocopy::{Immutable, IntoBytes}; #[repr(u32)] #[derive(Debug, Default, Immutable, IntoBytes)] enum RequestType { #[default] In = 0, Out = 1, Flush = 4, } #[repr(C)] #[derive(Debug, Default, Immutable, IntoBytes)] struct VirtioBlockRequest { request_type: RequestType, reserved: u32, sector: u64, } fn main() { let request = VirtioBlockRequest { request_type: RequestType::Flush, sector: 42, ..Default::default() }; assert_eq!( request.as_bytes(), &[4, 0, 0, 0, 0, 0, 0, 0, 42, 0, 0, 0, 0, 0, 0, 0] ); }
ãã㯠MMIO ã«ã¯é©ããŠããŸããïŒvolatile ãªèªã¿æžãã䜿çšããªãããïŒããããšãã° DMA ã«ãã£ãŠããŒããŠã§ã¢ãšå ±æãããæ§é äœããäœããã®å€éšã€ã³ã¿ãŒãã§ãŒã¹çµç±ã§éä¿¡ãããæ§é äœãæ±ãéã«ã¯æçšã§ãã
FromBytesã¯ãã©ã®ãããªãã€ããã¿ãŒã³ã§ãæå¹ã§ããåã«å¯ŸããŠå®è£ ã§ãããããä¿¡é Œã§ããªããã€ãåããã§ãå®å šã«å€æã§ããŸãã- ãããã®åã«å¯ŸããŠ
FromBytesã derive ããããšãããšå€±æããŸããããã¯ãRequestTypeãå€å¥åãšã㊠u32 ã®åãåŸããã¹ãŠã®å€ã䜿çšããŠããããã§ã¯ãªãããã®ãããã¹ãŠã®ãã€ããã¿ãŒã³ãæå¹ã§ã¯ãªãããã§ãã zerocopy::byteorderã«ã¯ããã€ããªãŒããŒãæèããæ°å€ããªããã£ãã®åããããŸããsrc/bare-metal/useful-crates/zerocopy-example/ã§cargo runã䜿ã£ãŠãã®äŸãå®è¡ããŠãã ãããïŒcrate äŸåé¢ä¿ããããããPlayground ã§ã¯å®è¡ãããŸãããïŒ
aarch64-paging
aarch64-paging ã¯ã¬ãŒãã䜿ããšãAArch64 ä»®æ³ã¡ã¢ãªã·ã¹ãã ã¢ãŒããã¯ãã£ã«åŸã£ãŠããŒãžããŒãã«ãäœæã§ããŸãã
// èäœæš© 2023 Google LLC // SPDX-License-Identifier: Apache-2.0 use aarch64_paging::{ idmap::IdMap, paging::{Attributes, MemoryRegion}, }; const ASID: usize = 1; const ROOT_LEVEL: usize = 1; // æçãããã³ã°ãæã€æ°ããããŒãžããŒãã«ãäœæããŸãã let mut idmap = IdMap::new(ASID, ROOT_LEVEL); // 2 MiB ã®ã¡ã¢ãªé åãèªã¿åãå°çšãšããŠãããããŸãã idmap.map_range( &MemoryRegion::new(0x80200000, 0x80400000), Attributes::NORMAL | Attributes::NON_GLOBAL | Attributes::READ_ONLY, ).unwrap(); // ããŒãžããŒãã«ãæå¹åããããã« `TTBR0_EL1` ãèšå®ããŸãã idmap.activate();
- ãã㯠Android ã® Protected VM Firmware ã§äœ¿çšãããŠããŸãã
- ãã®äŸã¯å®æ©ãŸã㯠QEMU äžã§å®è¡ããå¿ èŠããããããããåäœã§ç°¡åã«å®è¡ããæ¹æ³ã¯ãããŸããã
buddy_system_allocator
buddy_system_allocator ã¯ãåºæ¬çãªããã£ã·ã¹ãã ã¢ãã±ãŒã¿ãå®è£
ããã¯ã¬ãŒãã§ããããã¯ãLockedHeap ã䜿ã£ãŠ GlobalAlloc ãå®è£
ããæšæºã® alloc ã¯ã¬ãŒãã䜿ããããã«ãããã ïŒåã«èŠããšããïŒã«ããFrameAllocator ã䜿ã£ãŠå¥ã® ã¢ãã¬ã¹ç©ºéãå²ãåœãŠãããã«ã䜿çšã§ããŸããããšãã°ãPCI BAR çšã« MMIO 空éãå²ãåœãŠããããšããããŸã:
// Copyright 2023 Google LLC // SPDX-License-Identifier: Apache-2.0 use buddy_system_allocator::FrameAllocator; use core::alloc::Layout; fn main() { let mut allocator = FrameAllocator::<32>::new(); allocator.add_frame(0x200_0000, 0x400_0000); let layout = Layout::from_size_align(0x100, 0x100).unwrap(); let bar = allocator .alloc_aligned(layout) .expect("Failed to allocate 0x100 byte MMIO region"); println!("Allocated 0x100 byte MMIO region at {:#x}", bar); }
- PCI BAR ã¯åžžã«ããã®ãµã€ãºãšåãã¢ã©ã€ã³ã¡ã³ããæã¡ãŸãã
src/bare-metal/useful-crates/allocator-example/ã§cargo runãå®è¡ã㊠ãã®äŸãåãããŠãã ãããïŒã¯ã¬ãŒãã®äŸåé¢ä¿ããããããPlayground ã§ã¯å®è¡ã§ããŸãããïŒ
tinyvec
ããŒãå²ãåœãŠãè¡ããã«ãVec ã®ããã«ãµã€ãºå€æŽã§ãããã®ã欲ãããªãããšããããŸããtinyvec ã¯ãããæäŸããŸããããã¯é
åãŸãã¯ã¹ã©ã€ã¹ãåºç€ãšãããã¯ã¿ã§ãéçã«å²ãåœãŠãããšãã¹ã¿ãã¯äžã«é
眮ããããšãã§ãã䜿çšäžã®èŠçŽ æ°ã远跡ããå²ãåœãŠãããŠããæ°ãè¶
ããŠäœ¿ãããšãããšãããã¯ããŸãã
// Copyright 2023 Google LLC // SPDX-License-Identifier: Apache-2.0 use tinyvec::{ArrayVec, array_vec}; fn main() { let mut numbers: ArrayVec<[u32; 5]> = array_vec!(42, 66); println!("{numbers:?}"); numbers.push(7); println!("{numbers:?}"); numbers.remove(1); println!("{numbers:?}"); }
tinyvecã§ã¯ãåæåã®ããã«èŠçŽ åãDefaultãå®è£ ããŠããå¿ èŠããããŸãã- Rust Playground ã«ã¯
tinyvecãå«ãŸããŠããããããã®äŸã¯ã€ã³ã©ã€ã³ã§ãåé¡ãªãå®è¡ã§ããŸãã
spin
std::sync::Mutex ãšãstd::sync ã®ãã®ä»ã®åæããªããã£ãã¯ãcore ã alloc ã§ã¯å©çšã§ããŸãããç°ãªã CPU éã§ç¶æ
ãå
±æããå Žåãªã©ãåæãå
éšå¯å€æ§ãã©ã®ããã«ç®¡çããã°ããã®ã§ããããã
spin ã¯ã¬ãŒãã¯ããããã®ããªããã£ãã®å€ãã«ã€ããŠãã¹ãã³ããã¯ããŒã¹ã®åçç©ãæäŸããŸãã
// èäœæš© 2023 Google LLC // SPDX-License-Identifier: Apache-2.0 use spin::mutex::SpinMutex; static COUNTER: SpinMutex<u32> = SpinMutex::new(0); fn main() { dbg!(COUNTER.lock()); *COUNTER.lock() += 2; dbg!(COUNTER.lock()); }
- å²ã蟌ã¿ãã³ãã©å ã§ããã¯ãååŸããå Žåã¯ããããããã¯ãé¿ããããæ³šæããŠãã ããã
spinã«ã¯ããã±ãããã㯠mutex å®è£ ãstd::syncã®RwLockã»Barrierã»Onceã«çžåœãããã®ããããŠé å»¶åæåã®ããã®LazyããããŸããonce_cellã¯ã¬ãŒãã«ããspin::once::Onceãšã¯å°ãç°ãªãã¢ãããŒãã«ãããé å»¶åæåçšã®äŸ¿å©ãªåãããã€ããããŸãã- Rust Playground ã«ã¯
spinãå«ãŸããŠããããããã®äŸã¯ã€ã³ã©ã€ã³ã§ãåé¡ãªãå®è¡ã§ããŸãã
Android ã§ã®ãã¢ã¡ã¿ã«
AOSP ã§ãã¢ã¡ã¿ã«ã® Rust ãã€ããªããã«ãããã«ã¯ããŸã rust_ffi_static Soong ã«ãŒã«ã䜿ã£ãŠ Rust ã³ãŒãããã«ãããæ¬¡ã«ãªã³ã«ã¹ã¯ãªããä»ãã® cc_binary ã䜿ã£ãŠãã€ããªæ¬äœãçæãããã®åŸ raw_binary ã䜿ã£ãŠ ELF ãå®è¡å¯èœãª raw ãã€ããªã«å€æããå¿
èŠããããŸãã
rust_ffi_static {
name: "libvmbase_example",
defaults: ["vmbase_ffi_defaults"],
crate_name: "vmbase_example",
srcs: ["src/main.rs"],
rustlibs: [
"libvmbase",
],
}
cc_binary {
name: "vmbase_example",
defaults: ["vmbase_elf_defaults"],
srcs: [
"idmap.S",
],
static_libs: [
"libvmbase_example",
],
linker_scripts: [
"image.ld",
":vmbase_sections",
],
}
raw_binary {
name: "vmbase_example_bin",
stem: "vmbase_example.bin",
src: ":vmbase_example",
enabled: false,
target: {
android_arm64: {
enabled: true,
},
},
}
vmbase
aarch64 äžã§ crosvm äžã§åäœãã VM åãã«ãvmbase ã©ã€ãã©ãªã¯ããªã³ã«ã¹ã¯ãªãããšãã«ãã«ãŒã«çšã®äŸ¿å©ãªããã©ã«ãã«å ããŠããšã³ããªãã€ã³ããUART ã³ã³ãœãŒã«ãã®ã³ã°ãªã©ãæäŸããŸãã
// Copyright 2023 Google LLC // SPDX-License-Identifier: Apache-2.0 #![no_main] #![no_std] use vmbase::{main, println}; main!(main); pub fn main(arg0: u64, arg1: u64, arg2: u64, arg3: u64) { println!("Hello world"); }
main!ãã¯ãã¯ã¡ã€ã³é¢æ°ãæå®ãããã®é¢æ°ã¯vmbaseã®ãšã³ããªãã€ã³ãããåŒã³åºãããŸããvmbaseã®ãšã³ããªãã€ã³ãã¯ã³ã³ãœãŒã«ã®åæåãåŠçããã¡ã€ã³é¢æ°ãçµäºããå Žå㯠VM ãã·ã£ããããŠã³ããããã« PSCI_SYSTEM_OFF ãçºè¡ããŸãã
æŒç¿
PL031 ãªã¢ã«ã¿ã€ã ã¯ããã¯ããã€ã¹çšã®ãã©ã€ããŒãäœæããŸãã
æŒç¿ã確èªããããçšæãããŠããsolutionsãèŠãããšãã§ããŸãã
RTC ãã©ã€ããŒ
QEMU aarch64 virt ãã·ã³ã«ã¯ã0x9010000 ã« PL031 ãªã¢ã«ã¿ã€ã ã¯ããã¯ããããŸãããã® æŒç¿ã§ã¯ããã®ãã©ã€ããŒãäœæããŠãã ããã
- ããã䜿ã£ãŠçŸåšæå»ãã·ãªã¢ã«ã³ã³ãœãŒã«ã«è¡šç€ºããŠãã ãããæ¥ä»/æå»ã®ãã©ãŒãããã«ã¯
chronoã¯ã¬ãŒãã䜿çšã§ããŸãã - ãããã¬ãžã¹ã¿ãšçã®å²ã蟌ã¿ã¹ããŒã¿ã¹ã䜿ã£ãŠãæå®ãã æå»ãããšãã° 3 ç§åŸãŸã§ããžãŒãŠã§ã€ãããŠãã ãããïŒã«ãŒãå
ã§
core::hint::spin_loopãåŒã³åºããŠãã ãããïŒ - æéãããã°çºå±èª²é¡: RTC ãããã«ãã£ãŠçæãããå²ã蟌ã¿ãæå¹åããŠåŠçããŠãã ããã Arm Generic Interrupt Controller ãèšå®ããã«ã¯ã
arm-gicã¯ã¬ãŒãã§æäŸããã ãã©ã€ããŒã䜿çšã§ããŸãã- RTC å²ã蟌ã¿ã䜿çšããŠãã ããããã㯠GIC ã«
IntId::spi(2)ãšããŠæ¥ç¶ãããŠããŸãã - å²ã蟌ã¿ãæå¹ã«ãããã
arm_gic::wfi()ã䜿ã£ãŠã³ã¢ãã¹ãªãŒãç¶æ ã«ã§ããŸããããã«ãããã³ã¢ã¯ å²ã蟌ã¿ãåä¿¡ãããŸã§ã¹ãªãŒãããŸãã
- RTC å²ã蟌ã¿ã䜿çšããŠãã ããããã㯠GIC ã«
æŒç¿ãã³ãã¬ãŒã ãããŠã³ããŒããã rtc ãã£ã¬ã¯ããªå
ã®æ¬¡ã®ãã¡ã€ã«ã確èªããŠãã ããã
src/main.rs:
// Copyright 2023 Google LLC // SPDX-License-Identifier: Apache-2.0 #![no_main] #![no_std] mod exceptions; mod logger; use aarch64_paging::descriptor::El1Attributes; use aarch64_rt::{InitialPagetable, entry, initial_pagetable}; use arm_gic::gicv3::registers::{Gicd, GicrSgi}; use arm_gic::gicv3::{GicCpuInterface, GicV3}; use arm_pl011_uart::{PL011Registers, Uart}; use core::panic::PanicInfo; use core::ptr::NonNull; use log::{LevelFilter, error, info, trace}; use safe_mmio::UniqueMmioPointer; use smccc::Hvc; use smccc::psci::system_off; /// Base addresses of the GICv3. const GICD_BASE_ADDRESS: NonNull<Gicd> = NonNull::new(0x800_0000 as _).unwrap(); const GICR_BASE_ADDRESS: NonNull<GicrSgi> = NonNull::new(0x80A_0000 as _).unwrap(); /// Base address of the primary PL011 UART. const PL011_BASE_ADDRESS: NonNull<PL011Registers> = NonNull::new(0x900_0000 as _).unwrap(); /// Attributes to use for device memory in the initial identity map. const DEVICE_ATTRIBUTES: El1Attributes = El1Attributes::VALID .union(El1Attributes::ATTRIBUTE_INDEX_0) .union(El1Attributes::ACCESSED) .union(El1Attributes::UXN); /// Attributes to use for normal memory in the initial identity map. const MEMORY_ATTRIBUTES: El1Attributes = El1Attributes::VALID .union(El1Attributes::ATTRIBUTE_INDEX_1) .union(El1Attributes::INNER_SHAREABLE) .union(El1Attributes::ACCESSED) .union(El1Attributes::NON_GLOBAL); initial_pagetable!({ let mut idmap = [0; 512]; // 1 GiB of device memory. idmap[0] = DEVICE_ATTRIBUTES.bits(); // 1 GiB of normal memory. idmap[1] = MEMORY_ATTRIBUTES.bits() | 0x40000000; // Another 1 GiB of device memory starting at 256 GiB. idmap[256] = DEVICE_ATTRIBUTES.bits() | 0x4000000000; InitialPagetable(idmap) }); entry!(main); fn main(x0: u64, x1: u64, x2: u64, x3: u64) -> ! { // SAFETY: `PL011_BASE_ADDRESS` is the base address of a PL011 device, and // nothing else accesses that address range. let uart = unsafe { Uart::new(UniqueMmioPointer::new(PL011_BASE_ADDRESS)) }; logger::init(uart, LevelFilter::Trace).unwrap(); info!("main({:#x}, {:#x}, {:#x}, {:#x})", x0, x1, x2, x3); // SAFETY: `GICD_BASE_ADDRESS` and `GICR_BASE_ADDRESS` are the base // addresses of a GICv3 distributor and redistributor respectively, and // nothing else accesses those address ranges. let mut gic = unsafe { GicV3::new( UniqueMmioPointer::new(GICD_BASE_ADDRESS), GICR_BASE_ADDRESS, 1, false, ) }; gic.setup(0); // TODO: RTC ãã©ã€ããŒã®ã€ã³ã¹ã¿ã³ã¹ãäœæããçŸåšæå»ã衚瀺ããã // TODO: 3 ç§åŸ æ©ããã system_off::<Hvc>().unwrap(); panic!("system_off returned"); } #[panic_handler] fn panic(info: &PanicInfo) -> ! { error!("{info}"); system_off::<Hvc>().unwrap(); loop {} }
src/exceptions.rsïŒããã倿Žããå¿ èŠãããã®ã¯ãæŒç¿ã®ç¬¬ 3 éšåã ãã®ã¯ãã§ãïŒ:
#![allow(unused)] fn main() { // Copyright 2023 Google LLC // SPDX-License-Identifier: Apache-2.0 // Copyright 2023 Google LLC // SPDX-License-Identifier: Apache-2.0 // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. use aarch64_rt::{ExceptionHandlers, RegisterStateRef, exception_handlers}; use arm_gic::InterruptGroup; use arm_gic::gicv3::GicCpuInterface; use log::{error, info, trace}; use smccc::Hvc; use smccc::psci::system_off; struct Handlers; impl ExceptionHandlers for Handlers { extern "C" fn sync_current(_state: RegisterStateRef) { error!("sync_current"); system_off::<Hvc>().unwrap(); } extern "C" fn irq_current(_state: RegisterStateRef) { trace!("irq_current"); let intid = GicCpuInterface::get_and_acknowledge_interrupt(InterruptGroup::Group1) .expect("No pending interrupt"); info!("IRQ {intid:?}"); } extern "C" fn fiq_current(_state: RegisterStateRef) { error!("fiq_current"); system_off::<Hvc>().unwrap(); } extern "C" fn serror_current(_state: RegisterStateRef) { error!("serror_current"); system_off::<Hvc>().unwrap(); } extern "C" fn sync_lower(_state: RegisterStateRef) { error!("sync_lower"); system_off::<Hvc>().unwrap(); } extern "C" fn irq_lower(_state: RegisterStateRef) { error!("irq_lower"); system_off::<Hvc>().unwrap(); } extern "C" fn fiq_lower(_state: RegisterStateRef) { error!("fiq_lower"); system_off::<Hvc>().unwrap(); } extern "C" fn serror_lower(_state: RegisterStateRef) { error!("serror_lower"); system_off::<Hvc>().unwrap(); } } exception_handlers!(Handlers); }
src/logger.rsïŒããã¯å€æŽããå¿ èŠã¯ãªãã¯ãã§ãïŒ:
#![allow(unused)] fn main() { // Copyright 2023 Google LLC // SPDX-License-Identifier: Apache-2.0 // Copyright 2023 Google LLC // SPDX-License-Identifier: Apache-2.0 // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. use arm_pl011_uart::Uart; use core::fmt::Write; use log::{LevelFilter, Log, Metadata, Record, SetLoggerError}; use spin::mutex::SpinMutex; static LOGGER: Logger = Logger { uart: SpinMutex::new(None) }; struct Logger { uart: SpinMutex<Option<Uart<'static>>>, } impl Log for Logger { fn enabled(&self, _metadata: &Metadata) -> bool { true } fn log(&self, record: &Record) { writeln!( self.uart.lock().as_mut().unwrap(), "[{}] {}", record.level(), record.args() ) .unwrap(); } fn flush(&self) {} } /// Initialises UART logger. pub fn init( uart: Uart<'static>, max_level: LevelFilter, ) -> Result<(), SetLoggerError> { LOGGER.uart.lock().replace(uart); log::set_logger(&LOGGER)?; log::set_max_level(max_level); Ok(()) } }
Cargo.tomlïŒããã¯å€æŽããå¿ èŠã¯ãªãã¯ãã§ãïŒ:
[workspace]
[package]
name = "rtc"
version = "0.1.0"
edition = "2024"
publish = false
[dependencies]
aarch64-paging = { version = "0.12.1", default-features = false }
aarch64-rt = "0.4.3"
arm-gic = "0.8.1"
arm-pl011-uart = "0.5.0"
bitflags = "2.11.1"
chrono = { version = "0.4.44", default-features = false }
log = "0.4.29"
safe-mmio = "0.3.0"
smccc = "0.2.2"
spin = "0.10.0"
zerocopy = "0.8.48"
build.rsïŒããã¯å€æŽããå¿ èŠã¯ãªãã¯ãã§ãïŒ:
// Copyright 2025 Google LLC
// SPDX-License-Identifier: Apache-2.0
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
fn main() {
println!("cargo:rustc-link-arg=-Timage.ld");
println!("cargo:rustc-link-arg=-Tmemory.ld");
println!("cargo:rerun-if-changed=memory.ld");
}
memory.ldïŒããã¯å€æŽããå¿ èŠã¯ãªãã¯ãã§ãïŒ:
/*
* Copyright 2023 Google LLC
* SPDX-License-Identifier: Apache-2.0
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* https://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
MEMORY
{
image : ORIGIN = 0x40080000, LENGTH = 2M
}
MakefileïŒããã¯å€æŽããå¿ èŠã¯ãªãã¯ãã§ãïŒ:
# Copyright 2023 Google LLC
# SPDX-License-Identifier: Apache-2.0
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.
.PHONY: build qemu_minimal qemu qemu_logger
all: rtc.bin
build:
cargo build
rtc.bin: build
cargo objcopy -- -O binary $@
qemu: rtc.bin
qemu-system-aarch64 -machine virt,gic-version=3 -cpu max -serial mon:stdio -display none -kernel $< -s
clean:
cargo clean
rm -f *.bin
.cargo/config.tomlïŒããã¯å€æŽããå¿ èŠã¯ãªãã¯ãã§ãïŒ:
[build]
target = "aarch64-unknown-none"
QEMU ã§ã³ãŒããå®è¡ããã«ã¯ make qemu ãå®è¡ããŠãã ããã
ãã¢ã¡ã¿ã« Rust ååŸ
RTC ãã©ã€ã
main.rs:
// èäœæš© 2023 Google LLC // SPDX-License-Identifier: Apache-2.0 #![no_main] #![no_std] mod exceptions; mod logger; mod pl031; use crate::pl031::Rtc; use arm_gic::{IntId, Trigger, irq_enable, wfi}; use chrono::{TimeZone, Utc}; use core::hint::spin_loop; use aarch64_paging::descriptor::El1Attributes; use aarch64_rt::{InitialPagetable, entry, initial_pagetable}; use arm_gic::gicv3::registers::{Gicd, GicrSgi}; use arm_gic::gicv3::{GicCpuInterface, GicV3}; use arm_pl011_uart::{PL011Registers, Uart}; use core::panic::PanicInfo; use core::ptr::NonNull; use log::{LevelFilter, error, info, trace}; use safe_mmio::UniqueMmioPointer; use smccc::Hvc; use smccc::psci::system_off; /// Base addresses of the GICv3. const GICD_BASE_ADDRESS: NonNull<Gicd> = NonNull::new(0x800_0000 as _).unwrap(); const GICR_BASE_ADDRESS: NonNull<GicrSgi> = NonNull::new(0x80A_0000 as _).unwrap(); /// Base address of the primary PL011 UART. const PL011_BASE_ADDRESS: NonNull<PL011Registers> = NonNull::new(0x900_0000 as _).unwrap(); /// Attributes to use for device memory in the initial identity map. const DEVICE_ATTRIBUTES: El1Attributes = El1Attributes::VALID .union(El1Attributes::ATTRIBUTE_INDEX_0) .union(El1Attributes::ACCESSED) .union(El1Attributes::UXN); /// Attributes to use for normal memory in the initial identity map. const MEMORY_ATTRIBUTES: El1Attributes = El1Attributes::VALID .union(El1Attributes::ATTRIBUTE_INDEX_1) .union(El1Attributes::INNER_SHAREABLE) .union(El1Attributes::ACCESSED) .union(El1Attributes::NON_GLOBAL); initial_pagetable!({ let mut idmap = [0; 512]; // 1 GiB of device memory. idmap[0] = DEVICE_ATTRIBUTES.bits(); // 1 GiB of normal memory. idmap[1] = MEMORY_ATTRIBUTES.bits() | 0x40000000; // Another 1 GiB of device memory starting at 256 GiB. idmap[256] = DEVICE_ATTRIBUTES.bits() | 0x4000000000; InitialPagetable(idmap) }); /// Base address of the PL031 RTC. const PL031_BASE_ADDRESS: NonNull<pl031::Registers> = NonNull::new(0x901_0000 as _).unwrap(); /// The IRQ used by the PL031 RTC. const PL031_IRQ: IntId = IntId::spi(2); entry!(main); fn main(x0: u64, x1: u64, x2: u64, x3: u64) -> ! { // SAFETY: `PL011_BASE_ADDRESS` is the base address of a PL011 device, and // nothing else accesses that address range. let uart = unsafe { Uart::new(UniqueMmioPointer::new(PL011_BASE_ADDRESS)) }; logger::init(uart, LevelFilter::Trace).unwrap(); info!("main({:#x}, {:#x}, {:#x}, {:#x})", x0, x1, x2, x3); // SAFETY: `GICD_BASE_ADDRESS` and `GICR_BASE_ADDRESS` are the base // addresses of a GICv3 distributor and redistributor respectively, and // nothing else accesses those address ranges. let mut gic = unsafe { GicV3::new( UniqueMmioPointer::new(GICD_BASE_ADDRESS), GICR_BASE_ADDRESS, 1, false, ) }; gic.setup(0); // SAFETY: `PL031_BASE_ADDRESS` is the base address of a PL031 device, and // nothing else accesses that address range. let mut rtc = unsafe { Rtc::new(UniqueMmioPointer::new(PL031_BASE_ADDRESS)) }; let timestamp = rtc.read(); let time = Utc.timestamp_opt(timestamp.into(), 0).unwrap(); info!("RTC: {time}"); GicCpuInterface::set_priority_mask(0xff); gic.set_interrupt_priority(PL031_IRQ, None, 0x80).unwrap(); gic.set_trigger(PL031_IRQ, None, Trigger::Level).unwrap(); irq_enable(); gic.enable_interrupt(PL031_IRQ, None, true).unwrap(); // Wait for 3 seconds, without interrupts. let target = timestamp + 3; rtc.set_match(target); info!("Waiting for {}", Utc.timestamp_opt(target.into(), 0).unwrap()); trace!( "matched={}, interrupt_pending={}", rtc.matched(), rtc.interrupt_pending() ); while !rtc.matched() { spin_loop(); } trace!( "matched={}, interrupt_pending={}", rtc.matched(), rtc.interrupt_pending() ); info!("Finished waiting"); // Wait another 3 seconds for an interrupt. let target = timestamp + 6; info!("Waiting for {}", Utc.timestamp_opt(target.into(), 0).unwrap()); rtc.set_match(target); rtc.clear_interrupt(); rtc.enable_interrupt(true); trace!( "matched={}, interrupt_pending={}", rtc.matched(), rtc.interrupt_pending() ); while !rtc.interrupt_pending() { wfi(); } trace!( "matched={}, interrupt_pending={}", rtc.matched(), rtc.interrupt_pending() ); info!("Finished waiting"); system_off::<Hvc>().unwrap(); panic!("system_off returned"); } #[panic_handler] fn panic(info: &PanicInfo) -> ! { error!("{info}"); system_off::<Hvc>().unwrap(); loop {} }
pl031.rs:
#![allow(unused)] fn main() { // èäœæš© 2023 Google LLC // SPDX-License-Identifier: Apache-2.0 #[repr(C, align(4))] pub struct Registers { /// Data register dr: ReadPure<u32>, /// Match register mr: ReadPureWrite<u32>, /// Load register lr: ReadPureWrite<u32>, /// Control register cr: ReadPureWrite<u8>, _reserved0: [u8; 3], /// Interrupt Mask Set or Clear register imsc: ReadPureWrite<u8>, _reserved1: [u8; 3], /// Raw Interrupt Status ris: ReadPure<u8>, _reserved2: [u8; 3], /// Masked Interrupt Status mis: ReadPure<u8>, _reserved3: [u8; 3], /// Interrupt Clear Register icr: WriteOnly<u8>, _reserved4: [u8; 3], } /// Driver for a PL031 real-time clock. #[derive(Debug)] pub struct Rtc<'a> { registers: UniqueMmioPointer<'a, Registers>, } impl<'a> Rtc<'a> { /// Constructs a new instance of the RTC driver for a PL031 device with the /// given set of registers. pub fn new(registers: UniqueMmioPointer<'a, Registers>) -> Self { Self { registers } } /// Reads the current RTC value. pub fn read(&self) -> u32 { field_shared!(self.registers, dr).read() } /// Writes a match value. When the RTC value matches this then an interrupt /// will be generated (if it is enabled). pub fn set_match(&mut self, value: u32) { field!(self.registers, mr).write(value); } /// Returns whether the match register matches the RTC value, whether or not /// the interrupt is enabled. pub fn matched(&self) -> bool { let ris = field_shared!(self.registers, ris).read(); (ris & 0x01) != 0 } /// Returns whether there is currently an interrupt pending. /// /// This should be true if and only if `matched` returns true and the /// interrupt is masked. pub fn interrupt_pending(&self) -> bool { let mis = field_shared!(self.registers, mis).read(); (mis & 0x01) != 0 } /// Sets or clears the interrupt mask. /// /// When the mask is true the interrupt is enabled; when it is false the /// interrupt is disabled. pub fn enable_interrupt(&mut self, mask: bool) { let imsc = if mask { 0x01 } else { 0x00 }; field!(self.registers, imsc).write(imsc); } /// Clears a pending interrupt, if any. pub fn clear_interrupt(&mut self) { field!(self.registers, icr).write(0x01); } } }
Rust ã®äžŠè¡æ§ãžãããã
Rust ã¯ããã¥ãŒããã¯ã¹ããã£ãã«ãåãã OS ã¹ã¬ããã䜿çšããäžŠè¡æ§ã å®å šã«ãµããŒãããŠããŸãã
Rust ã®åã·ã¹ãã ã¯ãå€ãã®äžŠè¡æ§ãã°ãã³ã³ãã€ã«æãšã©ãŒã«ããããã§ éèŠãªåœ¹å²ãæãããŸãããã®èãæ¹ã¯ fearless concurrency ãšã㊠ç¥ãããŠãããå®è¡æã®æ£ãããã³ã³ãã€ã©ã«é Œã£ãŠä¿èšŒã§ããããã§ãã
ã¹ã±ãžã¥ãŒã«
session outline
- Rust ã§ã¯ãã¹ã¬ãããåæããªããã£ããªã©ãOS ã®äžŠè¡åŠçããŒã«ããããå©çšã§ããŸãã
- åã·ã¹ãã ã«ãããç¹å¥ãªæ©èœããªããŠãäžŠè¡æ§ã®å®å šæ§ãåŸãããŸãã
- åäžã¹ã¬ããã§ã®ã䞊è¡ãããã¢ã¯ã»ã¹ïŒããšãã°ãåŒã³åºããã颿°ãåŒæ°ãå€æŽ ãããããããžã®åç §ãä¿åããŠåŸã§èªãã ãããå ŽåïŒã«åœ¹ç«ã€ã®ãšåã ããŒã«ãããã«ãã¹ã¬ããã®åé¡ãããç§ãã¡ãå®ã£ãŠãããŸãã
ã¹ã¬ãã
segment outline
éåžžã®ã¹ã¬ãã
Rust ã®ã¹ã¬ããã¯ãä»ã®èšèªã®ã¹ã¬ãããšåæ§ã«åäœããŸã:
// Copyright 2024 Google LLC // SPDX-License-Identifier: Apache-2.0 use std::thread; use std::time::Duration; fn main() { thread::spawn(|| { for i in 0..10 { println!("Count in thread: {i}!"); thread::sleep(Duration::from_millis(5)); } }); for i in 0..5 { println!("Main thread: {i}"); thread::sleep(Duration::from_millis(5)); } }
- æ°ããã¹ã¬ãããçæããŠãã
mainã®æåŸã§ããã°ã©ã ã®çµäºãèªåçã« é ããããããšã¯ãããŸããã - ã¹ã¬ããã® panic ã¯äºãã«ç¬ç«ããŠããŸãã
- panic ã¯ãã€ããŒããæã€ããšãã§ãããã®å
容ã¯
Any::downcast_refã§åãåºããŸãã
- panic ã¯ãã€ããŒããæã€ããšãã§ãããã®å
容ã¯
-
ãã®äŸãå®è¡ããŸãã
- 5ms ãšããã¿ã€ãã³ã°ã«ã¯ååãªäœè£ããããããmain ã¹ã¬ãããšçæãã ã¹ã¬ããã¯ã»ãŒè¶³äžŠã¿ãããããŠé²ã¿ãŸãã
- çæããã¹ã¬ããã 10 ã«å°éããåã«ããã°ã©ã ãçµäºããããšã«æ³šç®ã㊠ãã ããã
- ããã¯
mainãããã°ã©ã ãçµäºãããçæããã¹ã¬ããã¯ããã°ã©ã ã åç¶ãããªãããã§ãã- å¿
èŠã§ããã°ã
pthreads/C++std::thread/boost::threadãšæ¯èŒã㊠ã¿ãŠãã ããã
- å¿
èŠã§ããã°ã
-
çæããã¹ã¬ãããå®äºãããŸã§åŸ ã€ã«ã¯ãã©ãããã°ããã§ããããã
-
thread::spawnã¯JoinHandleãè¿ããŸããããã¥ã¡ã³ããèŠãŠãã ãããJoinHandleã«ã¯ããããã¯ãã.join()ã¡ãœããããããŸãã
-
let handle = thread::spawn(...)ãšããåŸã§handle.join()ã䜿ã£ãŠ ã¹ã¬ããã®çµäºãåŸ ã€ãšãããã°ã©ã ã¯æåŸãŸã§æ°ã㊠10 ã«å°éããŸãã -
ã§ã¯ãå€ãè¿ãããå Žåã¯ã©ãã§ããããã
-
ããäžåºŠããã¥ã¡ã³ããèŠãŠãã ãã:
thread::spawnã®ã¯ããŒãžã£ã¯Tãè¿ããŸãJoinHandleã®.join()ã¯thread::Result<T>ãè¿ããŸã
-
handle.join()ã®Resultã®æ»ãå€ã䜿ã£ãŠãè¿ãããå€ã«ã¢ã¯ã»ã¹ããŸãã -
ã§ã¯ãããäžæ¹ã®ã±ãŒã¹ã¯ã©ãã§ããããã
- ã¹ã¬ããã§ panic ãçºçãããŸããããã«ãã£ãŠ
main㯠panic ããªãããšã« 泚ç®ããŠãã ããã - panic ã®ãã€ããŒãã«ã¢ã¯ã»ã¹ããŸããããã§
Anyã«ã€ããŠèª¬æããã®ã« ã¡ããã©ããã¿ã€ãã³ã°ã§ãã
- ã¹ã¬ããã§ panic ãçºçãããŸããããã«ãã£ãŠ
-
ããã§ã¹ã¬ããããå€ãè¿ããããã«ãªããŸãããã§ã¯ãå ¥åãåãåãã«ã¯ ã©ãããã°ããã§ããããã
- ã¹ã¬ããã®ã¯ããŒãžã£ã§äœããåç §ãšããŠãã£ããã£ããŸãã
- ãšã©ãŒã¡ãã»ãŒãžã¯ãããã move ããªããã°ãªããªãããšã瀺ããŸãã
- ããã move ãããšãèšç®ããŠããæŽŸçããå€ãè¿ããããšãããããŸãã
-
åçšãããå Žåã¯ã©ãã§ããããã
mainã¯æ»ããšãã«åã¹ã¬ãããçµäºãããŸãããå¥ã®é¢æ°ã§ããã°åã« æ»ã£ãŠãããããå®è¡ãããŸãŸã«ããŠããŸããŸãã- ããã¯ã¹ã¿ã㯠use-after-return ã§ãããã¡ã¢ãªå®å šæ§ã«éåããŸã!
- ãããã©ãé¿ããã°ããã§ãããããæ¬¡ã®ã¹ã©ã€ããèŠãŠãã ããã
ã¹ã³ãŒãä»ãã¹ã¬ãã
éåžžã®ã¹ã¬ããã¯ãåšå²ã®ç°å¢ããåçšããããšã¯ã§ããŸãã:
// Copyright 2024 Google LLC // SPDX-License-Identifier: Apache-2.0 use std::thread; fn foo() { let s = String::from("Hello"); thread::spawn(|| { dbg!(s.len()); }); } fn main() { foo(); }
ãã ãããã®å Žåã¯ã¹ã³ãŒãä»ãã¹ã¬ããã䜿ããŸã:
// Copyright 2024 Google LLC // SPDX-License-Identifier: Apache-2.0 use std::thread; fn foo() { let s = String::from("Hello"); thread::scope(|scope| { scope.spawn(|| { dbg!(s.len()); }); }); } fn main() { foo(); }
- ãã®çç±ã¯ã
thread::scope颿°ãå®äºãããšããã¹ãŠã® ã¹ã¬ããã join ãããŠããããšãä¿èšŒããããããåçšããããŒã¿ãè¿ããããã§ãã - éåžžã® Rust ã®åçšã«ãŒã«ãé©çšãããŸãã1 ã€ã®ã¹ã¬ããã«ããå¯å€åçšãã ä»»æåã®ã¹ã¬ããã«ããäžå€åçšã®ããããäžæ¹ã ããå¯èœã§ãã
ãã£ãã«
segment outline
Sender ãš Receiver
Rust ã®ãã£ãã«ã¯ 2 ã€ã®éšåããæããŸã: Sender<T> ãš Receiver<T> ã§ãããã® 2 ã€ã®éšåã¯ãã£ãã«ãä»ããŠæ¥ç¶ãããŠããŸãããèŠããã®ã¯ãšã³ããã€ã³ãã ãã§ãã
// Copyright 2024 Google LLC // SPDX-License-Identifier: Apache-2.0 use std::sync::mpsc; fn main() { let (tx, rx) = mpsc::channel(); tx.send(10).unwrap(); tx.send(20).unwrap(); println!("Received: {:?}", rx.recv()); println!("Received: {:?}", rx.recv()); let tx2 = tx.clone(); tx2.send(30).unwrap(); println!("Received: {:?}", rx.recv()); }
mpsc㯠Multi-Producer, Single-Consumer ã®ç¥ã§ããSenderãšSyncSenderã¯Cloneãå®è£ ããŠãããããè€æ°ã®éä¿¡åŽãäœæã§ããŸãããReceiverã¯å®è£ ããŠããŸãããsend()ãšrecv()ã¯Resultãè¿ããŸããErrãè¿ãããå Žåã察å¿ããSenderãŸãã¯Receiverãããããããããã£ãã«ãéããããŠããããšãæå³ããŸãã
éå¢çãã£ãã«
mpsc::channel() ã䜿ããšãéå¢çãã€éåæã®ãã£ãã«ãååŸã§ããŸã:
// Copyright 2022 Google LLC // SPDX-License-Identifier: Apache-2.0 use std::sync::mpsc; use std::thread; use std::time::Duration; fn main() { let (tx, rx) = mpsc::channel(); thread::spawn(move || { let thread_id = thread::current().id(); for i in 0..10 { tx.send(format!("Message {i}")).unwrap(); println!("{thread_id:?}: sent Message {i}"); } println!("{thread_id:?}: done"); }); thread::sleep(Duration::from_millis(100)); for msg in rx { println!("Main: got {msg}"); } }
- éå¢çãã£ãã«ã¯ãä¿çäžã®ã¡ãã»ãŒãžãæ ŒçŽããããã«å¿
èŠãªã ãã®é åãå²ãåœãŠãŸãã
send()ã¡ãœããã¯åŒã³åºãå ã®ã¹ã¬ããããããã¯ããŸããã - ãã£ãã«ãéããããŠããå Žåã
send()ã®åŒã³åºãã¯ãšã©ãŒã§å€±æããŸãïŒãã®ããResultãè¿ããŸãïŒãåä¿¡åŽãããããããããšããã£ãã«ã¯éããããŸãã
æçãã£ãã«
æçïŒåæïŒãã£ãã«ã§ã¯ãsend() ãçŸåšã®ã¹ã¬ããããããã¯ããããšããããŸã:
// Copyright 2022 Google LLC // SPDX-License-Identifier: Apache-2.0 use std::sync::mpsc; use std::thread; use std::time::Duration; fn main() { let (tx, rx) = mpsc::sync_channel(3); thread::spawn(move || { let thread_id = thread::current().id(); for i in 0..10 { tx.send(format!("Message {i}")).unwrap(); println!("{thread_id:?}: sent Message {i}"); } println!("{thread_id:?}: done"); }); thread::sleep(Duration::from_millis(100)); for msg in rx { println!("Main: got {msg}"); } }
send()ãåŒã³åºããšãæ°ããã¡ãã»ãŒãžãå ¥ãã空ãããã£ãã«ã« ã§ãããŸã§ãçŸåšã®ã¹ã¬ããã¯ãããã¯ãããŸãããã£ãã«ãã èªã¿åããã®ã誰ãããªãå Žåãã¹ã¬ããã¯ç¡æéã«ãããã¯ãããå¯èœæ§ã ãããŸãã- ç¡çãã£ãã«ãšåæ§ã«ããã£ãã«ãéããããŠããå Žåã
send()ã® åŒã³åºãã¯ãšã©ãŒãè¿ããŠå€±æããŸãã - ãµã€ãºã 0 ã®æçãã£ãã«ã¯ãã©ã³ãããŒãã£ãã«ããšåŒã°ããŸãããã¹ãŠã® éä¿¡ã¯ãå¥ã®ã¹ã¬ããã
recv()ãåŒã³åºããŸã§ãçŸåšã®ã¹ã¬ããããããã¯ããŸãã
Send ãš Sync
segment outline
ããŒã«ãŒãã¬ã€ã
Rust ã¯ã©ã®ããã«ããŠãã¹ã¬ããããŸããå ±æã¢ã¯ã»ã¹ãçŠæ¢ãã¹ãã ãšå€æããŠããã®ã§ããããããã®çãã¯ã次㮠2 ã€ã®ãã¬ã€ãã«ãããŸãã
Send: åTã¯ãTãã¹ã¬ããå¢çããŸããã§ç§»åããŠãå®å šã§ããå Žåã«Sendã§ããSync: åTã¯ã&Tãã¹ã¬ããå¢çããŸããã§ç§»åããŠãå®å šã§ããå Žåã«Syncã§ãã
Send ãš Sync 㯠unsafe ãã¬ã€ã ã§ããã³ã³ãã€ã©ã¯ããããã Send ãš Sync ãªåã ããå«ãéããããªãã®åã«å¯ŸããŠããããèªåçã«å°åºããŸããããã劥åœã ãšåãã£ãŠããå Žåã¯ãæåã§å®è£
ããããšãã§ããŸãã
- ãããã®ãã¬ã€ãã¯ããã®åãç¹å®ã®ã¹ã¬ããå®å šæ§ã®æ§è³ªãæã€ããšã瀺ãããŒã«ãŒãšèããããšãã§ããŸãã
- éåžžã®ãã¬ã€ããšåæ§ã«ããžã§ããªãã¯å¶çŽã§äœ¿çšã§ããŸãã
Send
å
Tã¯ãTåã®å€ãå¥ã®ã¹ã¬ãããžç§»åããŠãå®å šã§ããå Žåã«Sendã§ãã
æææš©ãå¥ã®ã¹ã¬ããã«ç§»ããšããã¹ãã©ã¯ã¿ ã¯ãã®ã¹ã¬ããã§å®è¡ãããŸãããããã£ãŠåé¡ãšãªãã®ã¯ãããã¹ã¬ããã§å€ãå²ãåœãŠãå¥ã®ã¹ã¬ããã§ãããè§£æŸã§ããã®ã¯ã©ã®ãããªå Žåããšããããšã§ãã
ããšãã°ãSQLite ã©ã€ãã©ãªãžã®æ¥ç¶ã¯åäžã®ã¹ã¬ããããã®ã¿ã¢ã¯ã»ã¹ããªããã°ãªããŸããã
Sync
å
TãSyncã§ããã®ã¯ãè€æ°ã®ã¹ã¬ããããåæã«Tåã®å€ãžå®å šã«ã¢ã¯ã»ã¹ã§ããå Žåã§ãã
ããæ£ç¢ºã«ã¯ãå®çŸ©ã¯æ¬¡ã®ãšããã§ãã
TãSyncã§ããã®ã¯ã&TãSendã§ããå Žåãã€ãã®å Žåã«éããŸã
ãã®èšè¿°ã¯æ¬è³ªçã«ã¯ãããåãå ±æããŠäœ¿çšããŠãã¹ã¬ããã»ãŒãã§ãããªãããã®åãžã®åç §ãã¹ã¬ããéã§åãæž¡ãããšãã¹ã¬ããã»ãŒãã§ããããšããããšãç°¡æœã«è¡šãããã®ã§ãã
ããã¯ãããåã Sync ã§ãããªããããŒã¿ç«¶åããã®ä»ã®åæã«é¢ããåé¡ã®å±éºãªãããã®åãè€æ°ã®ã¹ã¬ããéã§å
±æã§ããããšãæå³ãããããå¥ã®ã¹ã¬ãããžç§»ããŠãå®å
šã ããã§ãããã®åãžã®åç
§ããåç
§å
ã®ããŒã¿ã«ã¯ã©ã®ã¹ã¬ããããã§ãå®å
šã«ã¢ã¯ã»ã¹ã§ãããããå¥ã®ã¹ã¬ãããžç§»ããŠãå®å
šã§ãã
äŸ
Send + Sync
ããèŠãããã»ãšãã©ã®å㯠Send + Sync ã§ã:
i8ãf32ãboolãcharã&strãªã©(T1, T2)ã[T; N]ã&[T]ãstruct { x: T }ãªã©StringãOption<T>ãVec<T>ãBox<T>ãªã©Arc<T>: ã¢ãããã¯ãªåç §ã«ãŠã³ãã«ãã£ãŠæç€ºçã«ã¹ã¬ããã»ãŒãã§ããMutex<T>: å éšããã¯ã«ãã£ãŠæç€ºçã«ã¹ã¬ããã»ãŒãã§ããmpsc::Sender<T>: 1.72.0 以éãAtomicBool,AtomicU8, âŠ: ç¹å¥ãªã¢ãããã¯åœä»€ã䜿çšããŸãã
ãžã§ããªãã¯åã¯ãåãã©ã¡ãŒã¿ã Send + Sync ã§ããã°ãéåžž Send + Sync ã§ãã
Send + !Sync
ãããã®åã¯ä»ã®ã¹ã¬ããã«ç§»åã§ããŸãããã¹ã¬ããã»ãŒãã§ã¯ãããŸããã éåžžã¯ãå éšå¯å€æ§ãããããã§ã:
mpsc::Receiver<T>Cell<T>RefCell<T>
!Send + Sync
ãããã®åã¯è€æ°ã®ã¹ã¬ããããïŒå ±æåç §ãä»ããŠïŒå®å šã«ã¢ã¯ã»ã¹ã§ããŸããã å¥ã®ã¹ã¬ããã«ç§»åããããšã¯ã§ããŸãã:
MutexGuard<T>: äœæããã¹ã¬ããäžã§è§£æŸããªããã°ãªããªã OS ã¬ãã«ã® ããªããã£ãã䜿çšããŸãããã ãããã§ã«ããã¯ãããŠãã mutex ã§ã¯ã ã¬ãŒããå ±æãããŠããä»»æã®ã¹ã¬ãããããã®ä¿è·å¯Ÿè±¡ã®å€æ°ãèªã¿åãããšã ã§ããŸãïŒãã ãTèªäœã!Syncã®å Žåãé€ããŸãïŒã
!Send + !Sync
ãããã®åã¯ã¹ã¬ããã»ãŒãã§ã¯ãªããä»ã®ã¹ã¬ããã«ç§»åããããšãã§ããŸãã:
Rc<T>: åRc<T>ã¯RcBox<T>ãžã®åç §ãæã£ãŠããããã®äžã«ã¯ éã¢ãããã¯ãªåç §ã«ãŠã³ããå«ãŸããŠããŸãã*const T,*mut T: Rust ã¯ãçãã€ã³ã¿ã«ã¯ç¹å¥ãªäžŠè¡æ§ã«é¢ããèæ ®äºé ã ããå¯èœæ§ããããšæ³å®ããŠããŸãã
å ±æç¶æ
segment outline
Arc
Arc<T> ã¯ãArc::clone ã䜿ã£ãŠå
±æã®èªã¿åãå°çšæææš©ãå®çŸããŸã:
// Copyright 2024 Google LLC // SPDX-License-Identifier: Apache-2.0 use std::sync::Arc; use std::thread; /// ã©ã®ã¹ã¬ããããããããããããããåºåããæ§é äœã #[derive(Debug)] struct WhereDropped(Vec<i32>); impl Drop for WhereDropped { fn drop(&mut self) { println!("Dropped by {:?}", thread::current().id()) } } fn main() { let v = Arc::new(WhereDropped(vec![10, 20, 30])); let mut handles = Vec::new(); for i in 0..5 { let v = Arc::clone(&v); handles.push(thread::spawn(move || { // 0ã500ms ã¹ãªãŒãããŸãã std::thread::sleep(std::time::Duration::from_millis(500 - i * 100)); let thread_id = thread::current().id(); println!("{thread_id:?}: {v:?}"); })); } // ããã§ãçæãããã¹ã¬ããã ãã `v` ã®ã¯ããŒã³ãä¿æããŸãã drop(v); // æåŸã«çæãããã¹ã¬ãããçµäºãããšã`v` ã®å 容ããããããããŸãã handles.into_iter().for_each(|h| h.join().unwrap()); }
Arc㯠âAtomic Reference Countedâ ã®ç¥ã§ãã¢ãããã¯æäœã䜿çšããRcã®ã¹ã¬ããã»ãŒãçã§ããArc<T>ã¯ãTãCloneãå®è£ ããŠãããã©ããã«é¢ä¿ãªãCloneãå®è£ ããŸããTãSendãšSyncã®äž¡æ¹ãå®è£ ããŠããå Žåã«éããããããå®è£ ããŸããArc::clone()ã«ã¯å®è¡ãããã¢ãããã¯æäœã®ã³ã¹ãããããŸããããã®åŸã®Tã®å©çšèªäœã«ã¯ã³ã¹ããããããŸããã- åç
§ãµã€ã¯ã«ã«æ³šæããŠãã ããã
Arcã¯ããããæ€åºããããã®ã¬ããŒãžã³ã¬ã¯ã¿ã䜿çšããŸãããstd::sync::Weakã圹ç«ã¡ãŸãã
Mutex
Mutex<T> ã¯çžäºæä»ãä¿èšŒããã〠èªã¿åãå°çšã€ã³ã¿ãŒãã§ãŒã¹è¶ãã« T ãžã®å¯å€ã¢ã¯ã»ã¹ãå¯èœã«ããŸãïŒå
éšå¯å€æ§ ã®å¥ã®åœ¢ã§ãïŒ:
// Copyright 2024 Google LLC // SPDX-License-Identifier: Apache-2.0 use std::sync::Mutex; fn main() { let v = Mutex::new(vec![10, 20, 30]); println!("v: {:?}", v.lock().unwrap()); { let mut guard = v.lock().unwrap(); guard.push(40); } println!("v: {:?}", v.lock().unwrap()); }
ããã§ impl<T: Send> Sync for Mutex<T> ãšãããã©ã³ã±ãã å®è£
ãããããšã«æ³šç®ããŠãã ããã
- Rust ã®
Mutexã¯ããã 1 ã€ã®èŠçŽ â ä¿è·å¯Ÿè±¡ã®ããŒã¿ â ã ããæã€ ã³ã¬ã¯ã·ã§ã³ã®ããã«èŠããŸãã- ä¿è·å¯Ÿè±¡ã®ããŒã¿ã«ã¢ã¯ã»ã¹ããåã«ãã¥ãŒããã¯ã¹ãååŸãå¿ããããšã¯ ãããŸããã
&Mutex<T>ã®ããã¯ãååŸããããšã§&mut TãåŸãããŸããMutexGuardã¯ã&mut Tã®å¯¿åœãããã¯ã®ä¿ææéãè¶ ããªãããšãä¿èšŒããŸããTãSendãå®è£ ããŠããå Žåã«éããMutex<T>ã¯SendãšSyncã®äž¡æ¹ãå®è£ ããŸãã- èªã¿æžãããã¯ã«å¯Ÿå¿ãããã®:
RwLockã - ãªã
lock()ã¯Resultãè¿ãã®ã§ããããïŒMutexãä¿æããŠããã¹ã¬ããã panic ãããšãMutexã¯ãä¿è·ããŠãã ããŒã¿ãäžæŽåãªç¶æ ã«ããå¯èœæ§ã瀺ãããã«ããã€ãºã³åããããŸãã ãã€ãºã³åããããã¥ãŒããã¯ã¹ã«å¯ŸããŠlock()ãåŒã³åºããšãPoisonErrorã§å€±æããŸãããšã©ãŒã«å¯ŸããŠinto_inner()ãåŒã³åºãã°ã ããã§ãããŒã¿ãå埩ã§ããŸãã
äŸ
Arc ãš Mutex ãå®éã«ã©ã®ããã«åäœããããèŠãŠã¿ãŸããã:
// èäœæš© 2024 Google LLC // SPDX-License-Identifier: Apache-2.0 use std::thread; // use std::sync::{Arc, Mutex}; fn main() { let v = vec![10, 20, 30]; let mut handles = Vec::new(); for i in 0..5 { handles.push(thread::spawn(|| { v.push(10 * i); println!("v: {v:?}"); })); } handles.into_iter().for_each(|h| h.join().unwrap()); }
è§£çäŸ:
// èäœæš© 2024 Google LLC // SPDX-License-Identifier: Apache-2.0 use std::sync::{Arc, Mutex}; use std::thread; fn main() { let v = Arc::new(Mutex::new(vec![10, 20, 30])); let mut handles = Vec::new(); for i in 0..5 { let v = Arc::clone(&v); handles.push(thread::spawn(move || { let mut v = v.lock().unwrap(); v.push(10 * i); println!("v: {v:?}"); })); } handles.into_iter().for_each(|h| h.join().unwrap()); }
泚ç®ãã¹ãç¹:
vã¯ArcãšMutexã®äž¡æ¹ã§ã©ãããããŠããŸããããã¯ããããããæ±ãé¢å¿äºã çŽäº€ããŠããããã§ããMutexãArcã§ã©ããããã®ã¯ãã¹ã¬ããéã§å¯å€ç¶æ ãå ±æããããã® äžè¬çãªãã¿ãŒã³ã§ãã
v: Arc<_>ã¯ãæ°ããçæãããåã¹ã¬ããçšã«æ°ããåç §ãäœãããã« ã¯ããŒã³ããå¿ èŠããããŸããã©ã ãã®ã·ã°ããã£ã«moveã远å ãããŠããç¹ã«æ³šæããŠãã ãããLockGuardã®ã¹ã³ãŒããå¯èœãªéãçããããã«ããããã¯ãå°å ¥ãããŠããŸãã
æŒç¿
segment outline
é£äºããå²åŠè
é£äºããå²åŠè åé¡ã¯ãäžŠè¡æ§ã«ãããå€å žçãªåé¡ã§ã:
5 人ã®å²åŠè ãåãããŒãã«ã§äžç·ã«é£äºãããŸããåå²åŠè ã«ã¯ ããŒãã«ã®èªåã®åžããããŸããåç¿ã®éã«ã¯ 1 æ¬ã®ç®žããããŸããåºãããæç㯠ã¹ãã²ããã£ã§ãé£ã¹ãã«ã¯ 2 æ¬ã®ç®žãå¿ èŠã§ããåå²åŠè 㯠èããããšãšé£ã¹ãããšã亀äºã«è¡ãããšããã§ããŸãããããã«ãå²åŠè ã ã¹ãã²ããã£ãé£ã¹ãããã®ã¯ãå·Šãšå³ã®ç®žã®äž¡æ¹ãæã£ãŠãããšãã ãã§ãããããã£ãŠ 2 æ¬ã®ç®žã 䜿ããã®ã¯ãå·Šå³ã®é£äºº 2 人ãé£ã¹ãŠããããèããŠãããšãã ãã§ãã ããããã®å²åŠè ã¯é£ã¹çµãããã äž¡æ¹ã®ç®žã眮ããŸãã
ãã®æŒç¿ãè¡ãã«ã¯ãããŒã«ã«ã« Cargo ãã€ã³ã¹ããŒã« ããŠããå¿
èŠããããŸãã 以äžã®ã³ãŒãã src/main.rs ãšãããã¡ã€ã«ã«ã³ããŒãã空æ¬ãåããŠã cargo run ããããããã¯ããªãããšã確èªããŠãã ãã:
// Copyright 2024 Google LLC // SPDX-License-Identifier: Apache-2.0 use std::sync::{Arc, Mutex, mpsc}; use std::thread; use std::time::Duration; struct Chopstick; struct Philosopher { name: String, // left_chopstick: ... // right_chopstick: ... // thoughts: ... } impl Philosopher { fn think(&self) { self.thoughts .send(format!("Eureka! {} has a new idea!", &self.name)) .unwrap(); } fn eat(&self) { // 箞ãåã... println!("{} is eating...", &self.name); thread::sleep(Duration::from_millis(10)); } } static PHILOSOPHERS: &[&str] = &["Socrates", "Hypatia", "Plato", "Aristotle", "Pythagoras"]; fn main() { // 箞ãäœæãã // å²åŠè ãäœæãã // ããããã« 100 åèããããŠé£ã¹ããã // 圌ãã®èããåºåãã }
以äžã® Cargo.toml ã䜿çšã§ããŸã:
[package]
name = "dining-philosophers"
version = "0.1.0"
edition = "2024"
- ãŸãã¯ãã»ãŒãåäœãã解決çã®å®è£ ã«éäžãããããåŠçã«ä¿ããŠãã ããã
- æãåçŽãªè§£æ±ºçã«ããããããããã¯ã¯ãäžè¬çãªäžŠè¡æ§ã®åé¡ã§ããã Rust ããã®çš®ã®ãã°ãèªåçã«é²ãã§ãããããã§ã¯ãªãããšã瀺ããŠããŸãã
ãã«ãã¹ã¬ããã®ãªã³ã¯ãã§ãã«ãŒ
æ°ããåŸãç¥èã䜿ã£ãŠããã«ãã¹ã¬ããã®ãªã³ã¯ãã§ãã«ãŒãäœæããŠã¿ãŸãããããã㯠Web ããŒãžããéå§ãããã®ããŒãžäžã®ãªã³ã¯ãæå¹ã§ããããšã確èªã§ããããã«ããå¿ èŠããããŸããåããã¡ã€ã³å ã®ä»ã®ããŒãžãååž°çã«ç¢ºèªãããã¹ãŠã®ããŒãžã®æ€èšŒãå®äºãããŸã§ãããç¶ããå¿ èŠããããŸãã
ããã«ã¯ãreqwest ã®ãã㪠HTTP ã¯ã©ã€ã¢ã³ããå¿
èŠã§ãããŸãããªã³ã¯ãèŠã€ããæ¹æ³ãå¿
èŠã§ãããscraper ã䜿ããŸããæåŸã«ããšã©ãŒãåŠçããããã®ææ®µãå¿
èŠãªã®ã§ãthiserror ã䜿çšããŸãã
æ°ãã Cargo ãããžã§ã¯ããäœæããæ¬¡ã®ããã« reqwest ãäŸåé¢ä¿ãšããŠè¿œå ããŸãã
cargo new link-checker
cd link-checker
cargo add --features blocking reqwest
cargo add scraper
cargo add thiserror
cargo addãerror: no such subcommandã§å€±æããå Žåã¯ãCargo.tomlãã¡ã€ã«ãæåã§ç·šéããŠãã ããã以äžã«ç€ºãäŸåé¢ä¿ã远å ããŸãã
cargo add ã®åŒã³åºãã«ãããCargo.toml ãã¡ã€ã«ã¯æ¬¡ã®ããã«æŽæ°ãããŸãã
[package]
name = "link-checker"
version = "0.1.0"
edition = "2024"
publish = false
[dependencies]
reqwest = { version = "0.13.1", features = ["blocking"] }
scraper = "0.25.0"
thiserror = "2.0.18"
ããã§éå§ããŒãžãããŠã³ããŒãã§ããŸããhttps://www.google.org/ ã®ãããªå°èŠæš¡ãªãµã€ãã§è©ŠããŠã¿ãŠãã ããã
src/main.rs ãã¡ã€ã«ã¯ã次ã®ããã«ãªããŸãã
// Copyright 2024 Google LLC // SPDX-License-Identifier: Apache-2.0 use reqwest::Url; use reqwest::blocking::Client; use scraper::{Html, Selector}; use thiserror::Error; #[derive(Error, Debug)] enum Error { #[error("request error: {0}")] ReqwestError(#[from] reqwest::Error), #[error("bad http response: {0}")] BadResponse(String), } #[derive(Debug)] struct CrawlCommand { url: Url, extract_links: bool, } fn visit_page(client: &Client, command: &CrawlCommand) -> Result<Vec<Url>, Error> { println!("Checking {:#}", command.url); let response = client.get(command.url.clone()).send()?; if !response.status().is_success() { return Err(Error::BadResponse(response.status().to_string())); } let mut link_urls = Vec::new(); if !command.extract_links { return Ok(link_urls); } let base_url = response.url().clone(); let body_text = response.text()?; let document = Html::parse_document(&body_text); let selector = Selector::parse("a").unwrap(); let href_values = document .select(&selector) .filter_map(|element| element.value().attr("href")); for href in href_values { match base_url.join(href) { Ok(link_url) => { link_urls.push(link_url); } Err(err) => { println!("On {base_url:#}: ignored unparsable {href:?}: {err}"); } } } Ok(link_urls) } fn main() { let client = Client::new(); let start_url = Url::parse("https://www.google.org").unwrap(); let crawl_command = CrawlCommand{ url: start_url, extract_links: true }; match visit_page(&client, &crawl_command) { Ok(links) => println!("Links: {links:#?}"), Err(err) => println!("Could not extract links: {err:#}"), } }
次ã®ã³ãã³ãã§ src/main.rs ã®ã³ãŒããå®è¡ããŸãã
cargo run
課é¡
- ã¹ã¬ããã䜿ã£ãŠãªã³ã¯ã䞊åã«ç¢ºèªããŸãã確èªå¯Ÿè±¡ã® URL ããã£ãã«ã«éããããã€ãã®ã¹ã¬ããã§ URL ã䞊åã«ç¢ºèªãããŠãã ããã
- ãããæ¡åŒµããŠã
www.google.orgãã¡ã€ã³äžã®ãã¹ãŠã®ããŒãžããååž°çã«ãªã³ã¯ãæœåºããŠãã ããããµã€ãã«ãããã¯ãããªãããã100 ããŒãžçšåºŠã®äžéãèšããŠãã ããã
- ããã¯è€éãªæŒç¿ã§ãããåŠçãä»ã®æŒç¿ããã倧ããªãããžã§ã¯ãã«åãçµãæ©äŒãåŸãããšãæå³ããŠããŸãããã®æŒç¿ã®æåæ¡ä»¶ã¯ãäœããã®ãçŸå®çãªãåé¡ã§è¡ãè©°ãŸããä»ã®åŠçãè¬åž«ã®æ¯æŽãåããªãããããä¹ãè¶ããããšã§ãã
è§£ç
é£äºããå²åŠè
// Copyright 2024 Google LLC // SPDX-License-Identifier: Apache-2.0 use std::sync::{Arc, Mutex, mpsc}; use std::thread; use std::time::Duration; struct Chopstick; struct Philosopher { name: String, left_chopstick: Arc<Mutex<Chopstick>>, right_chopstick: Arc<Mutex<Chopstick>>, thoughts: mpsc::SyncSender<String>, } impl Philosopher { fn think(&self) { self.thoughts .send(format!("Eureka! {} has a new idea!", &self.name)) .unwrap(); } fn eat(&self) { println!("{} is trying to eat", &self.name); let _left = self.left_chopstick.lock().unwrap(); let _right = self.right_chopstick.lock().unwrap(); println!("{} is eating...", &self.name); thread::sleep(Duration::from_millis(10)); } } static PHILOSOPHERS: &[&str] = &["Socrates", "Hypatia", "Plato", "Aristotle", "Pythagoras"]; fn main() { let (tx, rx) = mpsc::sync_channel(10); let chopsticks = PHILOSOPHERS .iter() .map(|_| Arc::new(Mutex::new(Chopstick))) .collect::<Vec<_>>(); for i in 0..chopsticks.len() { let tx = tx.clone(); let mut left_chopstick = Arc::clone(&chopsticks[i]); let mut right_chopstick = Arc::clone(&chopsticks[(i + 1) % chopsticks.len()]); // To avoid a deadlock, we have to break the symmetry // somewhere. This will swap the chopsticks without deinitializing // either of them. if i == chopsticks.len() - 1 { std::mem::swap(&mut left_chopstick, &mut right_chopstick); } let philosopher = Philosopher { name: PHILOSOPHERS[i].to_string(), thoughts: tx, left_chopstick, right_chopstick, }; thread::spawn(move || { for _ in 0..100 { philosopher.eat(); philosopher.think(); } }); } drop(tx); for thought in rx { println!("{thought}"); } }
ãªã³ã¯ãã§ãã«ãŒ
// Copyright 2024 Google LLC // SPDX-License-Identifier: Apache-2.0 use std::sync::{Arc, Mutex, mpsc}; use std::thread; use reqwest::Url; use reqwest::blocking::Client; use scraper::{Html, Selector}; use thiserror::Error; #[derive(Error, Debug)] enum Error { #[error("request error: {0}")] ReqwestError(#[from] reqwest::Error), #[error("bad http response: {0}")] BadResponse(String), } #[derive(Debug)] struct CrawlCommand { url: Url, extract_links: bool, } fn visit_page(client: &Client, command: &CrawlCommand) -> Result<Vec<Url>, Error> { println!("Checking {:#}", command.url); let response = client.get(command.url.clone()).send()?; if !response.status().is_success() { return Err(Error::BadResponse(response.status().to_string())); } let mut link_urls = Vec::new(); if !command.extract_links { return Ok(link_urls); } let base_url = response.url().clone(); let body_text = response.text()?; let document = Html::parse_document(&body_text); let selector = Selector::parse("a").unwrap(); let href_values = document .select(&selector) .filter_map(|element| element.value().attr("href")); for href in href_values { match base_url.join(href) { Ok(link_url) => { link_urls.push(link_url); } Err(err) => { println!("On {base_url:#}: ignored unparsable {href:?}: {err}"); } } } Ok(link_urls) } struct CrawlState { domain: String, visited_pages: std::collections::HashSet<String>, } impl CrawlState { fn new(start_url: &Url) -> CrawlState { let mut visited_pages = std::collections::HashSet::new(); visited_pages.insert(start_url.as_str().to_string()); CrawlState { domain: start_url.domain().unwrap().to_string(), visited_pages } } /// Determine whether links within the given page should be extracted. fn should_extract_links(&self, url: &Url) -> bool { url.domain().is_some_and(|d| d == self.domain) } /// Mark the given page as visited, returning false if it had already /// been visited. fn mark_visited(&mut self, url: &Url) -> bool { self.visited_pages.insert(url.as_str().to_string()) } } type CrawlResult = Result<Vec<Url>, (Url, Error)>; fn spawn_crawler_threads( command_receiver: mpsc::Receiver<CrawlCommand>, result_sender: mpsc::Sender<CrawlResult>, thread_count: u32, ) { // To multiplex the non-cloneable Receiver, wrap it in Arc<Mutex<_>>. let command_receiver = Arc::new(Mutex::new(command_receiver)); for _ in 0..thread_count { let result_sender = result_sender.clone(); let command_receiver = Arc::clone(&command_receiver); thread::spawn(move || { let client = Client::new(); loop { let command_result = { let receiver_guard = command_receiver.lock().unwrap(); receiver_guard.recv() }; let Ok(crawl_command) = command_result else { // The sender got dropped. No more commands coming in. break; }; let crawl_result = match visit_page(&client, &crawl_command) { Ok(link_urls) => Ok(link_urls), Err(error) => Err((crawl_command.url, error)), }; result_sender.send(crawl_result).unwrap(); } }); } } fn control_crawl( start_url: Url, command_sender: mpsc::Sender<CrawlCommand>, result_receiver: mpsc::Receiver<CrawlResult>, ) -> Vec<Url> { let mut crawl_state = CrawlState::new(&start_url); let start_command = CrawlCommand { url: start_url, extract_links: true }; command_sender.send(start_command).unwrap(); let mut pending_urls = 1; let mut bad_urls = Vec::new(); while pending_urls > 0 { let crawl_result = result_receiver.recv().unwrap(); pending_urls -= 1; match crawl_result { Ok(link_urls) => { for url in link_urls { if crawl_state.mark_visited(&url) { let extract_links = crawl_state.should_extract_links(&url); let crawl_command = CrawlCommand { url, extract_links }; command_sender.send(crawl_command).unwrap(); pending_urls += 1; } } } Err((url, error)) => { bad_urls.push(url); println!("Got crawling error: {:#}", error); } } } bad_urls } fn check_links(start_url: Url) -> Vec<Url> { let (result_sender, result_receiver) = mpsc::channel::<CrawlResult>(); let (command_sender, command_receiver) = mpsc::channel::<CrawlCommand>(); spawn_crawler_threads(command_receiver, result_sender, 16); control_crawl(start_url, command_sender, result_receiver) } fn main() { let start_url = reqwest::Url::parse("https://www.google.org").unwrap(); let bad_urls = check_links(start_url); println!("Bad URLs: {:#?}", bad_urls); }
ãããã
ãAsyncãã¯ãè€æ°ã®ã¿ã¹ã¯ã䞊è¡ããŠå®è¡ããäžŠè¡æ§ã¢ãã«ã§ããåã¿ã¹ã¯ãã ãããã¯ãããã«ãªããŸã§å®è¡ãããã®åŸãé²è¡å¯èœãªå¥ã®ã¿ã¹ã¯ã«åãæ¿ãã ããšã§åäœããŸãããã®ã¢ãã«ã«ãããéãããæ°ã®ã¹ã¬ããäžã§ãããå€ãã® ã¿ã¹ã¯ãå®è¡ã§ããŸããããã¯ãéåžžã¿ã¹ã¯ããšã®ãªãŒããŒããããéåžžã«äœãã ããã«ãªãã¬ãŒãã£ã³ã°ã·ã¹ãã ããç¶è¡å¯èœãª I/O ãå¹ççã«èå¥ããããã® ããªããã£ããæäŸããŠããããã§ãã
Rust ã®éåæåŠçã¯ãfutureãã«åºã¥ããŠãããããã¯å°æ¥å®äºããå¯èœæ§ã®ãã åŠçã衚ããŸããfuture ã¯ãå®äºããããšã瀺ããŸã§ãpollããããŸãã
future 㯠async ã©ã³ã¿ã€ã ã«ãã£ãŠ poll ãããããã€ãã®ç°ãªãã©ã³ã¿ã€ã ã å©çšã§ããŸãã
æ¯èŒ
-
Python ã§ã¯ã
asyncioã«åæ§ã®ã¢ãã«ããããŸãããã ãããã®Futureå㯠ã³ãŒã«ããã¯ããŒã¹ã§ãããpoll ãããŸãããPython ã®éåæããã°ã©ã ã«ã¯ã Rust ã®ã©ã³ã¿ã€ã ã«äŒŒããã«ãŒãããå¿ èŠã§ãã -
JavaScript ã®
Promiseã䌌ãŠããŸããããããã³ãŒã«ããã¯ããŒã¹ã§ããèšèª ã©ã³ã¿ã€ã ãã€ãã³ãã«ãŒããå®è£ ããŠãããããPromise ã®è§£æ±ºã«é¢ãã詳现㮠倧éšåã¯é ãããŠããŸãã
ã¹ã±ãžã¥ãŒã«
session outline
éåæã®åºæ¬
segment outline
async/await
倧ãŸãã«èšããšãasync Rust ã®ã³ãŒãã¯ãéåžžã®ã鿬¡ã³ãŒããšéåžžã«ãã䌌ãŠããŸã:
// Copyright 2024 Google LLC // SPDX-License-Identifier: Apache-2.0 use futures::executor::block_on; async fn count_to(count: i32) { for i in 0..count { println!("ã«ãŠã³ã㯠{i} ã§ã!"); } } async fn async_main(count: i32) { count_to(count).await; } fn main() { block_on(async_main(10)); }
èŠç¹:
-
ããã¯æ§æã瀺ãããã®ç°¡ç¥åãããäŸã§ããç¹ã«æ³šæããŠãã ããããã®äžã«ã¯ãé·æé å®è¡ãããåŠçããå®éã®äžŠè¡æ§ããããŸãã!
-
âasyncâ ããŒã¯ãŒãã¯ã·ã³ã¿ãã¯ã¹ã·ã¥ã¬ãŒã§ããã³ã³ãã€ã©ã¯æ»ãå€ã®åã future ã«çœ®ãæããŸãã
-
è¿ããã future ãã©ã®ããã«äœ¿ããã«ã€ããŠã³ã³ãã€ã©ãžã®è¿œå ã®æç€ºããªããã°ã
mainã async ã«ããããšã¯ã§ããŸããã -
async ã³ãŒããå®è¡ããã«ã¯ãšã°ãŒãã¥ãŒã¿ãå¿ èŠã§ãã
block_onã¯ãæå®ããã future ã®å®è¡ãå®äºãããŸã§çŸåšã®ã¹ã¬ããããããã¯ããŸãã -
.awaitã¯å¥ã®æäœã®å®äºãéåæã«åŸ æ©ããŸããblock_onãšç°ãªãã.awaitã¯çŸåšã®ã¹ã¬ããããããã¯ããŸããã -
.await㯠async 颿°ã®å éšã§ã®ã¿äœ¿çšã§ããŸãïŒãŸãã¯ãããã¯å ãããã㯠åŸã§ç޹ä»ããŸãïŒã
Future
Future ã¯ãã¬ã€ãã§ããã ãŸã å®äºããŠããªãå¯èœæ§ã®ããæäœã衚ããªããžã§ã¯ãã«ãã£ãŠå®è£
ãããŸãã Future ã¯ããŒãªã³ã°ã§ããpoll 㯠Poll ãè¿ããŸãã
#![allow(unused)] fn main() { // Copyright 2024 Google LLC // SPDX-License-Identifier: Apache-2.0 use std::pin::Pin; use std::task::Context; pub trait Future { type Output; fn poll(self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll<Self::Output>; } pub enum Poll<T> { Ready(T), Pending, } }
async 颿°ã¯ impl Future ãè¿ããŸããèªåã§å®çŸ©ããåã«å¯Ÿã㊠Future ãå®è£
ããããšãå¯èœã§ãïŒãã ãäžè¬çã§ã¯ãããŸããïŒãããšãã°ãtokio::spawn ããè¿ããã JoinHandle ã¯ããã®å®äºãåŸ
ãŠãããã« Future ãå®è£
ããŠããŸãã
Future ã«å¯Ÿã㊠.await ããŒã¯ãŒããé©çšãããšãçŸåšã® async 颿°ã¯ ãã® Future ã®æºåãæŽããŸã§äžæåæ¢ãããã®åŸãã®åºåã«ãªããŸãã
-
FutureåãšPollåã¯ãããã«ç€ºãããšããã«æ£ç¢ºã«å®è£ ãããŠããŸãããªã³ã¯ãã¯ãªãã¯ãããšã ããã¥ã¡ã³ãå ã§ãã®å®è£ ã衚瀺ã§ããŸãã -
Contextã«ãããã¿ã€ã ã¢ãŠããªã©ã®ã€ãã³ããçºçãããšãã«ãFuture 㯠å床ããŒãªã³ã°ãããããèªåèªèº«ãã¹ã±ãžã¥ãŒã«ã§ããŸãã -
Pinã¯ãFuture ãã¡ã¢ãªå ã§ç§»åããªãããšãä¿èšŒãããã® Future å ãæã ãã€ã³ã¿ãæå¹ãªãŸãŸã§ããããããã«ããŸããããã¯ã.awaitã®åŸã§ãåç §ãæå¹ãªãŸãŸã§ ããããããã«ããããã«å¿ èŠã§ããPinã«ã€ããŠã¯ãPitfallsãã®ã»ã°ã¡ã³ãã§æ±ããŸãã
ç¶æ æ©æ¢°
Rust 㯠async 颿°ãŸãã¯ãããã¯ãã颿°ã®é²è¡ç¶æ³ã远跡ããããã«ç¶æ
æ©æ¢°ã䜿ã£ãŠ Future ãå®è£
ããé ããåãžãšå€æããŸãããã®å€æã®è©³çްã¯è€éã§ãããäœãèµ·ããŠããã®ããæŠç¥çã«çè§£ããŠããããšã«ã¯æå³ããããŸããæ¬¡ã®é¢æ°ã¯
#![allow(unused)] fn main() { // Copyright 2025 Google LLC // SPDX-License-Identifier: Apache-2.0 /// 2 åã® D10 ããŒã«ã®åèšã«ä¿®æ£å€ãå ããŸãã async fn two_d10(modifier: u32) -> u32 { let first_roll = roll_d10().await; let second_roll = roll_d10().await; first_roll + second_roll + modifier } }
ããããæ¬¡ã®ãããªãã®ã«å€æãããŸãã
// Copyright 2025 Google LLC // SPDX-License-Identifier: Apache-2.0 use std::future::Future; use std::pin::Pin; use std::task::{Context, Poll}; /// 2 åã® D10 ããŒã«ã®åèšã«ä¿®æ£å€ãå ããŸãã fn two_d10(modifier: u32) -> TwoD10 { TwoD10::Init { modifier } } enum TwoD10 { // 颿°ã¯ãŸã éå§ãããŠããŸããã Init { modifier: u32 }, // æåã® `.await` ãå®äºããã®ãåŸ ã£ãŠããŸãã FirstRoll { modifier: u32, fut: RollD10Future }, // 2 åç®ã® `.await` ãå®äºããã®ãåŸ ã£ãŠããŸãã SecondRoll { modifier: u32, first_roll: u32, fut: RollD10Future }, } impl Future for TwoD10 { type Output = u32; fn poll(mut self: Pin<&mut Self>, ctx: &mut Context) -> Poll<Self::Output> { loop { match *self { TwoD10::Init { modifier } => { // æåã®ãã€ã¹ããŒã«çšã® Future ãäœæããŸãã let fut = roll_d10(); *self = TwoD10::FirstRoll { modifier, fut }; } TwoD10::FirstRoll { modifier, ref mut fut } => { // æåã®ãã€ã¹ããŒã«çšã®ãµã Future ã poll ããŸãã if let Poll::Ready(first_roll) = fut.poll(ctx) { // 2 åç®ã®ããŒã«çšã® Future ãäœæããŸãã let fut = roll_d10(); *self = TwoD10::SecondRoll { modifier, first_roll, fut }; } else { return Poll::Pending; } } TwoD10::SecondRoll { modifier, first_roll, ref mut fut } => { // 2 åç®ã®ãã€ã¹ããŒã«çšã®ãµã Future ã poll ããŸãã if let Poll::Ready(second_roll) = fut.poll(ctx) { return Poll::Ready(first_roll + second_roll + modifier); } else { return Poll::Pending; } } } } } }
ãã®äŸã¯èª¬æã®ããã®ãã®ã§ãããRust ã³ã³ãã€ã©ã®å€æãæ£ç¢ºã«è¡šãããã®ã§ã¯ãããŸãããããã§æ³šç®ãã¹ãéèŠãªç¹ã¯æ¬¡ã®ãšããã§ãã
- async 颿°ãåŒã³åºããŠããFuture ãæ§ç¯ããŠè¿ãã ãã§ããã以å€ã¯äœãèµ·ãããŸããã
- ãã¹ãŠã®ããŒã«ã«å€æ°ã¯ããã®é¢æ°ã® Future ã®äžã«æ ŒçŽãããenum ã䜿ã£ãŠå®è¡ãçŸåšã©ãã§äžæãããŠããããèå¥ããŸãã
- async 颿°å
ã®
.awaitã¯ãçåäžã®ãã¹ãŠã®å€æ°ãšåŸ æ©å¯Ÿè±¡ã® Future ãå«ãæ°ããç¶æ ãžãšå€æãããŸãããã®åŸloopããã®æŽæ°ãããç¶æ ãåŠçããFuture ãPoll::Readyãè¿ããŸã§ poll ãç¶ããŸãã - å®è¡ã¯
Poll::PendingãçºçãããŸã§ãã®ãŸãŸé²ã¿ç¶ããŸãããã®åçŽãªäŸã§ã¯ããã¹ãŠã® Future ãå³åº§ã« ready ã«ãªããŸãã mainã«ã¯çŽ æŽãªãšã°ãŒãã¥ãŒã¿ãå«ãŸããŠãããFuture ã®æºåãã§ãããŸã§åã«ããžãŒã«ãŒãããŸããå®éã®ãšã°ãŒãã¥ãŒã¿ã«ã€ããŠã¯åŸã»ã©èª¬æããŸãã
ããã«æãäžãã
æ·±ããã¹ããã async 颿°ã®ã¹ã¿ãã¯ã«å¯Ÿãã Future ããŒã¿æ§é ãæ³åããŠã¿ãŠãã ãããå颿°ã® Future ã«ã¯ããã®é¢æ°ãåŒã³åºã颿°ã® Future æ§é ãå«ãŸããŸãããã®çµæãã³ã³ãã€ã©ãçæãã Future åãäºæ³å€ã«å€§ãããªãããšããããŸãã
ããã¯ãŸããååž°ç㪠async 颿°ãé£ããããšãæå³ããŸããããšãã°ã次ã®ããã«ååž°åãæ§ç¯ããŠããŸãäžè¬çãªãšã©ãŒãšæ¯ã¹ãŠã¿ãŠãã ããã
#![allow(unused)] fn main() { // Copyright 2025 Google LLC // SPDX-License-Identifier: Apache-2.0 enum LinkedList<T> { Node { value: T, next: LinkedList<T> }, Nil, } }
ååž°åã®ä¿®æ£æ¹æ³ã¯ãBox ã®ããã«éæ¥åç
§ã®å±€ã 1 ã€è¿œå ããããšã§ããåæ§ã«ãååž°ç㪠async 颿°ã§ã¯ååž°ãã Future ãããã¯ã¹åããªããã°ãªããŸããã
// Copyright 2025 Google LLC // SPDX-License-Identifier: Apache-2.0 async fn count_to(n: u32) { if n > 0 { Box::pin(count_to(n - 1)).await; println!("{n}"); } }
ã©ã³ã¿ã€ã
ã©ã³ã¿ã€ã ã¯ãæäœãéåæã«å®è¡ããããã®ãµããŒãïŒãªã¢ã¯ã¿ãŒïŒãæäŸãã future ãå®è¡ãã責任ïŒãšã°ãŒãã¥ãŒã¿ãŒïŒãæ ããŸããRust ã«ã¯ âçµã¿èŸŒã¿â ã®ã©ã³ã¿ã€ã ã¯ãããŸããããããã€ãã®éžæè¢ããããŸãã
- Tokio: 髿§èœã§ãHTTP åãã® Hyper ã gRPC åãã® Tonic ã®ãããªæ©èœãå«ãã ããçºéãããšã³ã·ã¹ãã ããããŸãã
- smol: ã·ã³ãã«ã§è»œé
ããå€§èŠæš¡ãªã¢ããªã±ãŒã·ã§ã³ã®äžã«ã¯ãç¬èªã®ã©ã³ã¿ã€ã ãæã€ãã®ããããŸããããšãã°ã Fuchsia ã«ã¯ãã§ã«ãããŸãã
-
æããã©ã³ã¿ã€ã ã®ãã¡ãRust playground ã§ãµããŒããããŠããã®ã¯ Tokio ã ãã§ããç¹ã«æ³šæããŠãã ãããplayground ã§ã¯ I/O ãèš±å¯ãããŠããªããããå€ãã® è峿·±ã async åŠç㯠playground ã§ã¯å®è¡ã§ããŸããã
-
Future 㯠âäžæŽ»æ§â ã§ãããããããããŒãªã³ã°ãããšã°ãŒãã¥ãŒã¿ãŒãååšããªãéãã äœãè¡ããŸããïŒI/O æäœãéå§ããããšãããããŸããïŒãããã¯ãããšãã° JS ã® Promise ãšã¯ç°ãªããŸããJS ã® Promise ã¯ãããšãäžåºŠã䜿ãããªããŠãã å®äºãŸã§å®è¡ãããŸãã
Tokio
Tokio ã¯ä»¥äžãæäŸããŸãã
- éåæã³ãŒããå®è¡ããããã®ãã«ãã¹ã¬ããã©ã³ã¿ã€ã ã
- æšæºã©ã€ãã©ãªã®éåæçã
- å€§èŠæš¡ãªã©ã€ãã©ãªãšã³ã·ã¹ãã ã
// èäœæš© 2024 Google LLC // SPDX-License-Identifier: Apache-2.0 use tokio::time; async fn count_to(count: i32) { for i in 0..count { println!("Count in task: {i}!"); time::sleep(time::Duration::from_millis(5)).await; } } #[tokio::main] async fn main() { tokio::spawn(count_to(10)); for i in 0..5 { println!("Main task: {i}"); time::sleep(time::Duration::from_millis(5)).await; } }
-
tokio::mainãã¯ãã䜿ãããšã§ãmainã async ã«ã§ããããã«ãªããŸããã -
spawn颿°ã¯ãæ°ãã䞊è¡ãªãã¿ã¹ã¯ããäœæããŸãã -
泚:
spawnã¯Futureãåãåããããcount_toã«å¯ŸããŠ.awaitã¯åŒã³åºããŸããã
ããã«èª¿ã¹ãŠã¿ãŸããã:
-
ãªã
count_to㯠10 ãŸã§å°éããªãã®ã§ããããïŒãã㯠async ãã£ã³ã»ã«ã®äŸã§ããtokio::spawnã¯ãå®äºãŸã§åŸ æ©ããããã« await ã§ãããã³ãã«ãè¿ããŸãã -
spawn ãã代ããã«
count_to(10).awaitã詊ããŠã¿ãŠãã ããã -
tokio::spawnããè¿ãããã¿ã¹ã¯ã await ããŠã¿ãŠãã ããã
ã¿ã¹ã¯
Rust ã«ã¯ã¿ã¹ã¯ã·ã¹ãã ããããããã¯è»œéã¹ã¬ããã£ã³ã°ã®äžåœ¢æ ã§ãã
ã¿ã¹ã¯ã¯åäžã®ãããã¬ãã« Future ãæã¡ãexecutor ã¯ãããããŒãªã³ã°ããŠåŠçãé²ããŸãã ãã® Future ã¯ãpoll ã¡ãœãããããŒãªã³ã°ãã 1 ã€ä»¥äžã®ãã¹ãããã Future ãæã€å Žåãããã ããã¯å€§ãŸãã«ã¯ã³ãŒã«ã¹ã¿ãã¯ã«å¯Ÿå¿ããŸããã¿ã¹ã¯å
ã§ã®äžŠè¡æ§ã¯ã ã¿ã€ããŒãš I/O æäœãç«¶åãããããã«è€æ°ã®å Future ãããŒãªã³ã°ããããšã§å®çŸã§ããŸãã
// èäœæš© 2024 Google LLC // SPDX-License-Identifier: Apache-2.0 use tokio::io::{self, AsyncReadExt, AsyncWriteExt}; use tokio::net::TcpListener; #[tokio::main] async fn main() -> io::Result<()> { let listener = TcpListener::bind("127.0.0.1:0").await?; println!("listening on port {}", listener.local_addr()?.port()); loop { let (mut socket, addr) = listener.accept().await?; println!("connection from {addr:?}"); tokio::spawn(async move { socket.write_all(b"Who are you?\n").await.expect("socket error"); let mut buf = vec![0; 1024]; let name_size = socket.read(&mut buf).await.expect("socket error"); let name = std::str::from_utf8(&buf[..name_size]).unwrap().trim(); let reply = format!("Thanks for dialing in, {name}!\n"); socket.write_all(reply.as_bytes()).await.expect("socket error"); }); } }
ãã®äŸãçšæãã src/main.rs ã«ã³ããŒããããããå®è¡ããŠãã ããã
nc ã telnet ã®ãã㪠TCP æ¥ç¶ããŒã«ã䜿ã£ãŠæ¥ç¶ããŠã¿ãŠãã ããã
-
æ°äººã®ã¯ã©ã€ã¢ã³ããæ¥ç¶ããŠãããšãããã®ãµãŒããŒã®ç¶æ ãã©ããªã£ãŠããããåè¬è ã«ã€ã¡ãŒãžããŠããã£ãŠãã ãããã©ã®ãããªã¿ã¹ã¯ãååšããŸããïŒ ãããã® Future ã¯äœã§ããïŒ
-
ããã§åããŠ
asyncãããã¯ãèŠãŸãããããã¯ã¯ããŒãžã£ã«äŒŒãŠããŸããã åŒæ°ã¯åããŸããããã®æ»ãå€ã¯ Future ã§ãasync fnãšäŒŒãŠããŸãã -
async ãããã¯ã颿°ã«ãªãã¡ã¯ã¿ãªã³ã°ãã
?ã䜿ã£ãŠãšã©ãŒãã³ããªã³ã°ãæ¹åããŠãã ããã
ãã£ãã«ãšå¶åŸ¡ãããŒ
segment outline
éåæãã£ãã«
ããã€ãã®ã¯ã¬ãŒãã¯éåæãã£ãã«ããµããŒãããŠããŸããããšãã° tokio ã§ãã
// èäœæš© 2024 Google LLC // SPDX-License-Identifier: Apache-2.0 use tokio::sync::mpsc; async fn ping_handler(mut input: mpsc::Receiver<()>) { let mut count: usize = 0; while let Some(_) = input.recv().await { count += 1; println!("Received {count} pings so far."); } println!("ping_handler complete"); } #[tokio::main] async fn main() { let (sender, receiver) = mpsc::channel(32); let ping_handler_task = tokio::spawn(ping_handler(receiver)); for i in 0..10 { sender.send(()).await.expect("Failed to send ping."); println!("Sent {} pings so far.", i + 1); } drop(sender); ping_handler_task.await.expect("Something went wrong in ping handler task."); }
-
ãã£ãã«ãµã€ãºã
3ã«å€æŽããŠãå®è¡ã«ã©ã®ãããªåœ±é¿ããããã確èªããŠãã ããã -
å šäœãšããŠãã€ã³ã¿ãŒãã§ãŒã¹ã¯ ååã®ã¯ã©ã¹ ã§èŠã
syncãã£ãã«ã«äŒŒãŠããŸãã -
std::mem::dropåŒã³åºããåé€ããŠã¿ãŠãã ãããäœãèµ·ãããŸããïŒãªãã§ããïŒ -
Flume ã¯ã¬ãŒãã«ã¯ã
syncãšasyncã®sendããã³recvã®äž¡æ¹ãå®è£ ãããã£ãã«ããããŸããããã¯ãIO ãšéã CPU åŠçã¿ã¹ã¯ã®äž¡æ¹ãå«ãè€éãªã¢ããªã±ãŒã·ã§ã³ã§äŸ¿å©ã§ãã -
asyncãã£ãã«ãæ±ãããšãæãŸããçç±ã¯ãä»ã®futureãšçµã¿åãããŠãè€éãªå¶åŸ¡ãããŒãäœæã§ããç¹ã«ãããŸãã
Join
join æäœã¯ãäžé£ã® future ããã¹ãŠæºåã§ãããŸã§åŸ
æ©ãããããã®çµæã®ã³ã¬ã¯ã·ã§ã³ãè¿ããŸããããã¯ãJavaScript ã® Promise.all ã Python ã® asyncio.gather ã«äŒŒãŠããŸãã
// èäœæš© 2024 Google LLC // SPDX-License-Identifier: Apache-2.0 use anyhow::Result; use futures::future; use reqwest; use std::collections::HashMap; async fn size_of_page(url: &str) -> Result<usize> { let resp = reqwest::get(url).await?; Ok(resp.text().await?.len()) } #[tokio::main] async fn main() { let urls: [&str; 4] = [ "https://google.com", "https://httpbin.org/ip", "https://play.rust-lang.org/", "BAD_URL", ]; let futures_iter = urls.into_iter().map(size_of_page); let results = future::join_all(futures_iter).await; let page_sizes_dict: HashMap<&str, Result<usize>> = urls.into_iter().zip(results.into_iter()).collect(); println!("{page_sizes_dict:?}"); }
ãã®äŸãæºåãã src/main.rs ã«ã³ããŒããããããå®è¡ããŠãã ããã
-
åãç°ãªãè€æ°ã® future ã«å¯ŸããŠã¯
std::future::join!ã䜿ããŸãããã³ã³ãã€ã«æã« future ã®æ°ãåãã£ãŠããå¿ èŠããããŸããããã¯çŸåšã¯futuresã¯ã¬ãŒãã«ãããè¿ããã¡ã«std::futureã§å®å®åãããäºå®ã§ãã -
joinã®ãªã¹ã¯ã¯ãfuture ã® 1 ã€ã決ããŠè§£æ±ºããªãå¯èœæ§ãããããšã§ãããããªããšãããã°ã©ã ã¯åæ¢ãããŸãŸã«ãªããŸãã -
ããšãã°ãHTTP ãµãŒãã¹ãžã®ãã¹ãŠã®ãªã¯ãšã¹ããšããŒã¿ããŒã¹ã¯ãšãªããŸãšã㊠join ããããã«ã
join_allãšjoin!ãçµã¿åãããããšãã§ããŸããfutures::join!ã䜿ã£ãŠãfuture ã«tokio::time::sleepã远å ããŠã¿ãŠãã ãããããã¯ã¿ã€ã ã¢ãŠãã§ã¯ãããŸããïŒã¿ã€ã ã¢ãŠãã«ã¯select!ãå¿ èŠã§ã次ã®ç« ã§èª¬æããŸãïŒããjoin!ã瀺ããŠããŸãã
Select
select æäœã¯ãè€æ°ã® future ã®ãã¡ãããã 1 ã€ã®æºåãã§ãããŸã§åŸ
æ©ãããã® future ã®çµæã«å¿ããŠåŠçãè¡ããŸããJavaScript ã§ã¯ããã㯠Promise.race 㫠䌌ãŠããŸããPython ã§ã¯ã asyncio.wait(task_set, return_when=asyncio.FIRST_COMPLETED) ã«çžåœããŸãã
match æãšåæ§ã«ãselect! ã®æ¬äœã«ã¯è€æ°ã®ã¢ãŒã ãããããããã pattern = future => statement ãšãã圢åŒãåããŸããfuture ã®æºåãã§ãããšã ãã®æ»ãå€ã¯ pattern ã«ãã£ãŠåè§£ãããŸããç¶ããŠãåŸããã倿°ã䜿ã£ãŠ statement ãå®è¡ãããŸããstatement ã®çµæã select! ãã¯ãã®çµæã«ãªããŸãã
// èäœæš© 2024 Google LLC // SPDX-License-Identifier: Apache-2.0 use tokio::sync::mpsc; use tokio::time::{Duration, sleep}; #[tokio::main] async fn main() { let (tx, mut rx) = mpsc::channel(32); let listener = tokio::spawn(async move { tokio::select! { Some(msg) = rx.recv() => println!("got: {msg}"), _ = sleep(Duration::from_millis(50)) => println!("timeout"), }; }); sleep(Duration::from_millis(10)).await; tx.send(String::from("Hello!")).await.expect("Failed to send greeting"); listener.await.expect("Listener failed"); }
-
ããã§ã®
listenerasync ãããã¯ã¯äžè¬çãªåœ¢ã§ããäœããã® async ã€ãã³ãã ãŸãã¯ã¿ã€ã ã¢ãŠããåŸ ã¡ãŸããsleepãããé·ãããŠã倱æããããšã確èªã㊠ãã ããããã®ç¶æ³ã§sendã倱æããã®ã¯ãªãã§ããããïŒ -
ãã¢ã¯ã¿ãŒãã¢ãŒããã¯ãã£ã§ã¯ã
select!ã¯ã«ãŒãå ã§ããã䜿ãããŸããããã§ã¯ ã¿ã¹ã¯ãã«ãŒãå ã§ã€ãã³ãã«åå¿ããŸããããã«ã¯ããã€ãã®èœãšã穎ãããã ããã«ã€ããŠã¯æ¬¡ã®ã»ã°ã¡ã³ãã§èª¬æããŸãã
èœãšã穎
Async / await ã¯ã䞊è¡ãªéåæããã°ã©ãã³ã°ã®ããã®äŸ¿å©ã§å¹ççãªæœè±¡åã æäŸããŸããããããRust ã® async/await ã¢ãã«ã«ããçžå¿ã® èœãšã穎ãå±éºãªçœ ããããŸãããã®ç« ã§ã¯ããã®ããã€ãã瀺ããŸãã
segment outline
ãšã°ãŒãã¥ãŒã¿ããããã¯ãã
ã»ãšãã©ã® async ã©ã³ã¿ã€ã ã§ã¯ã䞊è¡ããŠå®è¡ã§ããã®ã¯ I/O ã¿ã¹ã¯ã ãã§ããããã¯ãCPU ããããã¯ããã¿ã¹ã¯ããšã°ãŒãã¥ãŒã¿ããããã¯ããã»ãã®ã¿ã¹ã¯ã®å®è¡ã劚ããããšãæå³ããŸããç°¡åãªåé¿çã¯ãå¯èœãªå Žå㯠async çžåœã®ã¡ãœããã䜿ãããšã§ãã
// èäœæš© 2024 Google LLC // SPDX-License-Identifier: Apache-2.0 use futures::future::join_all; use std::time::Instant; async fn sleep_ms(start: &Instant, id: u64, duration_ms: u64) { std::thread::sleep(std::time::Duration::from_millis(duration_ms)); println!( "future {id} slept for {duration_ms}ms, finished after {}ms", start.elapsed().as_millis() ); } #[tokio::main(flavor = "current_thread")] async fn main() { let start = Instant::now(); let sleep_futures = (1..=10).map(|t| sleep_ms(&start, t, t * 10)); join_all(sleep_futures).await; }
-
ã³ãŒããå®è¡ããsleep ã䞊è¡ã§ã¯ãªãé£ç¶ããŠçºçããããšã確èªããŠãã ããã
-
"current_thread"ãã¬ãŒããŒã§ã¯ããã¹ãŠã®ã¿ã¹ã¯ãåäžã®ã¹ã¬ããã«é 眮ãããŸããããã«ãããã®å¹æã¯ããåããããããªããŸããããã®ãã°ã¯ãã«ãã¹ã¬ããã®ãã¬ãŒããŒã§ãäŸç¶ãšããŠååšããŸãã -
std::thread::sleepãtokio::time::sleepã«çœ®ãæãããã®çµæã await ããŠãã ããã -
å¥ã®ä¿®æ£æ¹æ³ãšããŠã¯
tokio::task::spawn_blockingã䜿ãããšã§ããããã¯å®éã®ã¹ã¬ãããçæãããã®ãã³ãã«ããšã°ãŒãã¥ãŒã¿ããããã¯ããããšãªã future ã«å€æããŸãã -
ã¿ã¹ã¯ã OS ã¹ã¬ãããšããŠèããã¹ãã§ã¯ãããŸãããäž¡è 㯠1 察 1 ã«ã¯å¯Ÿå¿ããããšã°ãŒãã¥ãŒã¿ã§ã¯è€æ°ã®ã¿ã¹ã¯ãåäžã® OS ã¹ã¬ããäžã§å®è¡ã§ããŸããããã¯ãFFI çµç±ã§ä»ã®ã©ã€ãã©ãªãšããåãããå Žåã«ç¹ã«åé¡ã«ãªããŸãããã®ã©ã€ãã©ãªãã¹ã¬ããããŒã«ã«ã¹ãã¬ãŒãžã«äŸåããŠããããç¹å®ã® OS ã¹ã¬ããã«ãããããããããå¯èœæ§ãããããã§ãïŒäŸ: CUDAïŒããã®ãããªç¶æ³ã§ã¯
tokio::task::spawn_blockingãåªå ããŠãã ããã -
åæãã¥ãŒããã¯ã¹ã¯æ³šæããŠäœ¿çšããŠãã ããã
.awaitããŸããã§ãã¥ãŒããã¯ã¹ãä¿æãããšãå¥ã®ã¿ã¹ã¯ããããã¯ãããå¯èœæ§ãããããã®ã¿ã¹ã¯ã¯åãã¹ã¬ããäžã§å®è¡ãããŠãããããããŸããã
Pin
async 颿°ãŸãã¯ãããã¯ã¯ãFuture ãå®è£
ãããã¹ãŠã®ããŒã«ã«å€æ°ãå«ãåãäœæããããšãæãåºããŠãã ããããããã®å€æ°ã®äžéšã¯ãä»ã®ããŒã«ã«å€æ°ãžã®åç
§ïŒãã€ã³ã¿ïŒãä¿æã§ããŸããããããåžžã«æå¹ã§ããããšãä¿èšŒããããã«ããã® future ã¯å¥ã®ã¡ã¢ãªäœçœ®ãžç§»åãããŠã¯ãªããŸããã
future åãã¡ã¢ãªå
ã§ç§»åãããã®ãé²ãããã«ããã㯠pin ããããã€ã³ã¿ãéããŠã®ã¿ poll ã§ããŸããPin ã¯åç
§ãå
ãã©ãããŒã§ããããããæããŠããã€ã³ã¹ã¿ã³ã¹ãå¥ã®ã¡ã¢ãªäœçœ®ãžç§»åãããããããæäœãçŠæ¢ããŸãã
// Copyright 2024 Google LLC // SPDX-License-Identifier: Apache-2.0 use tokio::sync::{mpsc, oneshot}; use tokio::task::spawn; use tokio::time::{Duration, sleep}; // äœæ¥é ç®ããã®å Žåã¯ãæå®ãããæéã ã sleep ãã // `respond_on` ãã£ãã«ã§ã¡ãã»ãŒãžãè¿ããŸãã #[derive(Debug)] struct Work { input: u32, respond_on: oneshot::Sender<u32>, } // ãã¥ãŒäžã®äœæ¥ãåŸ ã¡åããŠå®è¡ããã¯ãŒã«ãŒã async fn worker(mut work_queue: mpsc::Receiver<Work>) { let mut iterations = 0; loop { tokio::select! { Some(work) = work_queue.recv() => { sleep(Duration::from_millis(10)).await; // äœæ¥ããŠãããµããããŸãã work.respond_on .send(work.input * 1000) .expect("failed to send response"); iterations += 1; } // TODO: 100ms ããšã«ååŸ©åæ°ãå ±åãã } } } // äœæ¥ãèŠæ±ãããã®å®äºãåŸ ã€ãªã¯ãšã¹ã¿ãŒã async fn do_work(work_queue: &mpsc::Sender<Work>, input: u32) -> u32 { let (tx, rx) = oneshot::channel(); work_queue .send(Work { input, respond_on: tx }) .await .expect("failed to send on work queue"); rx.await.expect("failed waiting for response") } #[tokio::main] async fn main() { let (tx, rx) = mpsc::channel(10); spawn(worker(rx)); for i in 0..100 { let resp = do_work(&tx, i).await; println!("work result for iteration {i}: {resp}"); } }
-
ãã㯠actor ãã¿ãŒã³ã®äŸã ãšæ°ã¥ãããããããŸãããactor ã¯éåžžãã«ãŒãå ã§
select!ãåŒã³åºããŸãã -
ããã¯åã®ããã€ãã®ã¬ãã¹ã³ã®ãŸãšãã«ããªã£ãŠããã®ã§ãæéããããŠåãçµãã§ãã ããã
-
çŽ æŽã«
_ = sleep(Duration::from_millis(100)) => { println!(..) }ãselect!ã«è¿œå ããŠã¿ãŠãã ãããããã¯æ±ºããŠå®è¡ãããŸããããªãã§ããããïŒ -
代ããã«ããã® future ãå«ã
timeout_futãloopã®å€åŽã«è¿œå ããŸãã#![allow(unused)] fn main() { // Copyright 2024 Google LLC // SPDX-License-Identifier: Apache-2.0 let timeout_fut = sleep(Duration::from_millis(100)); loop { select! { .., _ = timeout_fut => { println!(..); }, } } } -
ããã§ããŸã åäœããŸãããã³ã³ãã€ã©ãšã©ãŒã«åŸããmove ãåé¿ããããã«
select!å ã®timeout_futã«&mutã远å ãããã®åŸBox::pinã䜿ã£ãŠãã ããã#![allow(unused)] fn main() { // Copyright 2024 Google LLC // SPDX-License-Identifier: Apache-2.0 let mut timeout_fut = Box::pin(sleep(Duration::from_millis(100))); loop { select! { .., _ = &mut timeout_fut => { println!(..); }, } } } -
ããã¯ã³ã³ãã€ã«ã§ããŸããããã£ããã¿ã€ã ã¢ãŠããæéåãã«ãªããšãæ¯åã®å埩ã§
Poll::Readyã«ãªããŸãïŒãã®å Žåãfused future ã圹ç«ã¡ãŸãïŒãæéåãã«ãªããã³ã«timeout_futããªã»ããããããã«æŽæ°ããŠãã ããã#![allow(unused)] fn main() { // Copyright 2024 Google LLC // SPDX-License-Identifier: Apache-2.0 let mut timeout_fut = Box::pin(sleep(Duration::from_millis(100))); loop { select! { _ = &mut timeout_fut => { println!(..); timeout_fut = Box::pin(sleep(Duration::from_millis(100))); }, } } }
-
-
Box ã¯ããŒãã«å²ãåœãŠãŸããå Žåã«ãã£ãŠã¯ã
std::pin::pin!ïŒæ¯èŒçæè¿å®å®åãããå€ãã³ãŒãã§ã¯tokio::pin!ããã䜿ãããŠããŸããïŒãéžæè¢ã§ãããåä»£å ¥ããã future ã«å¯ŸããŠäœ¿ãã®ã¯é£ããã§ãã -
å¥ã®éžæè¢ãšããŠã
pinããŸã£ãã䜿ããã100ms ããšã«oneshotãã£ãã«ãžéä¿¡ããå¥ã®ã¿ã¹ã¯ã spawn ããæ¹æ³ããããŸãã -
èªåèªèº«ãžã®ãã€ã³ã¿ãå«ãããŒã¿ã¯ self-referential ãšåŒã°ããŸããéåžžãRust ã® borrow checker 㯠self-referential ãªããŒã¿ãç§»åãããããšãé²ããŸãããšããã®ããåç §ã¯ãã®åç §å ã®ããŒã¿ããé·ãçåã§ããªãããã§ããããããasync ãããã¯ã颿°ã«å¯Ÿããã³ãŒãå€æã¯ borrow checker ã«ãã£ãŠæ€èšŒãããŸããã
-
Pinã¯åç §ãå ãã©ãããŒã§ããpin ããããã€ã³ã¿ã䜿ããšããªããžã§ã¯ãããã®å Žæããç§»åã§ããŸããããã ããpin ãããŠããªããã€ã³ã¿ãéããŠã§ããã°ãäŸç¶ãšããŠç§»åã§ããŸãã -
Futureãã¬ã€ãã®pollã¡ãœããã¯ãã€ã³ã¹ã¿ã³ã¹ãåç §ããããã«&mut Selfã§ã¯ãªãPin<&mut Self>ã䜿ããŸããããããpin ããããã€ã³ã¿ã§ããåŒã³åºããªãçç±ã§ãã
Asyncãã¬ã€ã
ãã¬ã€ãå
ã® async ã¡ãœããã¯ã1.75 ãªãªãŒã¹ã§å®å®åãããŸãããããã«ã¯ããã¬ã€ãå
ã§æ»ãå€äœçœ®ã® impl Trait ã䜿ãããã®ãµããŒããå¿
èŠã§ãããasync fn ã®è±ç³ã§ã¯ -> impl Future<Output = ...> ãå«ãŸããããã§ãã
ãããããã€ãã£ããµããŒãããã£ãŠããasync fn ã«ã¯ããã€ãç¹æã®èœãšã穎ããããŸãã
-
æ»ãå€äœçœ®ã®
impl Traitã¯ãã¹ã³ãŒãå ã®ãã¹ãŠã®ã©ã€ãã¿ã€ã ããã£ããã£ããŸãïŒãã®ãããç¹å®ã®åçšãã¿ãŒã³ã¯è¡šçŸã§ããŸããïŒã -
async ãã¬ã€ã㯠trait objects ãšäžç·ã«ã¯äœ¿ããŸããïŒ
dyn Traitã¯ãµããŒããããŸããïŒã
async_trait ã¯ã¬ãŒãã¯ãããã€ãã®æ³šæç¹ã¯ãããã®ã®ããã¯ããéã㊠dyn ãµããŒãã®åé¿çãæäŸããŸãã
// Copyright 2024 Google LLC // SPDX-License-Identifier: Apache-2.0 use async_trait::async_trait; use std::time::Instant; use tokio::time::{Duration, sleep}; #[async_trait] trait Sleeper { async fn sleep(&self); } struct FixedSleeper { sleep_ms: u64, } #[async_trait] impl Sleeper for FixedSleeper { async fn sleep(&self) { sleep(Duration::from_millis(self.sleep_ms)).await; } } async fn run_all_sleepers_multiple_times( sleepers: Vec<Box<dyn Sleeper>>, n_times: usize, ) { for _ in 0..n_times { println!("Running all sleepers..."); for sleeper in &sleepers { let start = Instant::now(); sleeper.sleep().await; println!("Slept for {} ms", start.elapsed().as_millis()); } } } #[tokio::main] async fn main() { let sleepers: Vec<Box<dyn Sleeper>> = vec![ Box::new(FixedSleeper { sleep_ms: 50 }), Box::new(FixedSleeper { sleep_ms: 100 }), ]; run_all_sleepers_multiple_times(sleepers, 5).await; }
-
async_traitã¯ç°¡åã«äœ¿ããŸããããããå®çŸããããã«ããŒãå²ãåœãŠã䜿ã£ãŠããç¹ã«æ³šæããŠãã ããããã®ããŒãå²ãåœãŠã«ã¯æ§èœäžã®ãªãŒããŒãããããããŸãã -
async traitã®èšèªãµããŒãã«é¢ãã課é¡ã¯ããã®ææ¥ã§è©³ãã説æããã«ã¯ããŸãã«ãæ·±ããã®ã§ããããã«æãäžãããå Žåã¯ãNiko Matsakis ã«ãã this blog post ãåç §ããŠãã ãããæ¬¡ã®ããŒã¯ãŒããåç §ããŠãã ããã- RPIT: æ»ãå€äœçœ®ã®
impl Traitã®ç¥ã - RPITIT: ãã¬ã€ãå
ã®æ»ãå€äœçœ®
impl TraitïŒãã¬ã€ãå RPITïŒã®ç¥ã
- RPIT: æ»ãå€äœçœ®ã®
-
ã©ã³ãã ãªæéã ãã¹ãªãŒãããæ°ãã sleeper æ§é äœãäœæããããã
Vecã«è¿œå ããŠã¿ãŠãã ããã
ãã£ã³ã»ã«
future ããããããããšããã以éãã® future ãåã³ poll ãããããšã¯ ãããŸãããããã ãã£ã³ã»ã« ãšåŒã³ãããã¯ä»»æã® await ãã€ã³ãã§ çºçãåŸãŸããfuture ããã£ã³ã»ã«ãããå Žåã§ãã·ã¹ãã ãæ£ããåäœãã ããã«ã泚æãå¿
èŠã§ããããšãã°ããããããã¯ãããããŒã¿ã倱ã£ããããŠã¯ ãããŸããã
// Copyright 2024 Google LLC // SPDX-License-Identifier: Apache-2.0 use std::io; use std::time::Duration; use tokio::io::{AsyncReadExt, AsyncWriteExt, DuplexStream}; struct LinesReader { stream: DuplexStream, } impl LinesReader { fn new(stream: DuplexStream) -> Self { Self { stream } } async fn next(&mut self) -> io::Result<Option<String>> { let mut bytes = Vec::new(); let mut buf = [0]; while self.stream.read(&mut buf[..]).await? != 0 { bytes.push(buf[0]); if buf[0] == b'\n' { break; } } if bytes.is_empty() { return Ok(None); } let s = String::from_utf8(bytes) .map_err(|_| io::Error::new(io::ErrorKind::InvalidData, "not UTF-8"))?; Ok(Some(s)) } } async fn slow_copy(source: String, mut dest: DuplexStream) -> io::Result<()> { for b in source.bytes() { dest.write_u8(b).await?; tokio::time::sleep(Duration::from_millis(10)).await } Ok(()) } #[tokio::main] async fn main() -> io::Result<()> { let (client, server) = tokio::io::duplex(5); let handle = tokio::spawn(slow_copy("hi\nthere\n".to_owned(), client)); let mut lines = LinesReader::new(server); let mut interval = tokio::time::interval(Duration::from_millis(60)); loop { tokio::select! { _ = interval.tick() => println!("tick!"), line = lines.next() => if let Some(l) = line? { print!("{}", l) } else { break }, } } handle.await.unwrap()?; Ok(()) }
-
ã³ã³ãã€ã©ã¯ãã£ã³ã»ã«å®å šæ§ã«ã€ããŠã¯å©ããŠãããŸãããAPI ããã¥ã¡ã³ããèªã¿ã
async fnãã©ã®ãããªç¶æ ãä¿æããŠãããã èããå¿ èŠããããŸãã -
panicã?ãšç°ãªãããã£ã³ã»ã«ã¯ïŒãšã©ãŒãã³ããªã³ã°ã§ã¯ ãªãïŒéåžžã®å¶åŸ¡ãããŒã®äžéšã§ãã -
ãã®äŸã§ã¯ãæååã®äžéšã倱ãããŸãã
-
tick()åå²ãå ã«å®äºãããã³ã«ãnext()ãšãã®bufã ãããããããŸãã -
bufãæ§é äœã®äžéšã«ããã°ãLinesReaderããã£ã³ã»ã«å®å šã« ã§ããŸã:#![allow(unused)] fn main() { // Copyright 2024 Google LLC // SPDX-License-Identifier: Apache-2.0 struct LinesReader { stream: DuplexStream, bytes: Vec<u8>, buf: [u8; 1], } impl LinesReader { fn new(stream: DuplexStream) -> Self { Self { stream, bytes: Vec::new(), buf: [0] } } async fn next(&mut self) -> io::Result<Option<String>> { // buf ãš bytes ã« self. ãä»ããã // ... let raw = std::mem::take(&mut self.bytes); let s = String::from_utf8(raw) .map_err(|_| io::Error::new(io::ErrorKind::InvalidData, "not UTF-8"))?; // ... } } }
-
-
Interval::tickã¯ãtick ããã§ã«ãéç¥æžã¿ããã©ããã远跡ããŠããããã ãã£ã³ã»ã«å®å šã§ãã -
AsyncReadExt::readã¯ã埩垰ãããããŸã£ããããŒã¿ãèªã¿åããªããã®ã©ã¡ããã§ããããã ãã£ã³ã»ã«å®å šã§ãã -
AsyncBufReadExt::read_lineã¯ãã®äŸãšäŒŒãŠããããã£ã³ã»ã«å®å šã§ã¯ãããŸããã詳现ãšä»£æ¿ææ®µã« ã€ããŠã¯ããã®ããã¥ã¡ã³ããåç §ããŠãã ããã
æŒç¿
segment outline
é£äºããå²åŠè â Async
åé¡ã®èª¬æã«ã€ããŠã¯ãé£äºããå²åŠè ãåç §ããŠãã ããã
ååãšåæ§ã«ããã®æŒç¿ã«ã¯ããŒã«ã«ã® Cargo ã®ã€ã³ã¹ããŒã« ãå¿
èŠã§ãã以äžã® ã³ãŒãã src/main.rs ãšãããã¡ã€ã«ã«ã³ããŒãã空æ¬ãåããŠã cargo run ããããããã¯ããªãããšã確èªããŠãã ãã:
// Copyright 2024 Google LLC // SPDX-License-Identifier: Apache-2.0 use std::sync::Arc; use tokio::sync::{Mutex, mpsc}; use tokio::time; struct Chopstick; struct Philosopher { name: String, // left_chopstick: ... // right_chopstick: ... // thoughts: ... } impl Philosopher { async fn think(&self) { self.thoughts .send(format!("Eureka! {} has a new idea!", &self.name)) .await .unwrap(); } async fn eat(&self) { // Keep trying until we have both chopsticks println!("{} is eating...", &self.name); time::sleep(time::Duration::from_millis(5)).await; } } // tokio scheduler doesn't deadlock with 5 philosophers, so have 2. static PHILOSOPHERS: &[&str] = &["Socrates", "Hypatia"]; #[tokio::main] async fn main() { // 箞ãäœæãã // å²åŠè ãäœæãã // èãããé£ã¹ããããã // 圌ãã®èããåºåãã }
ä»å㯠Async Rust ã䜿çšãããããtokio ãžã®äŸåé¢ä¿ãå¿
èŠã§ããæ¬¡ã® Cargo.toml ã䜿çšã§ããŸã:
[package]
name = "dining-philosophers-async-dine"
version = "0.1.0"
edition = "2024"
[dependencies]
tokio = { version = "1.26.0", features = ["sync", "time", "macros", "rt-multi-thread"] }
ãŸããä»å㯠tokio ã¯ã¬ãŒãã® Mutex ãš mpsc ã¢ãžã¥ãŒã«ã䜿çšããªããã°ãªããªãç¹ã«ã泚æããŠãã ããã
- å®è£ ãã·ã³ã°ã«ã¹ã¬ããã«ã§ããŸããïŒ
ãããŒããã£ã¹ããã£ããã¢ããªã±ãŒã·ã§ã³
ãã®æŒç¿ã§ã¯ãæ°ãã身ã«ã€ããç¥èã䜿ã£ãŠããããŒããã£ã¹ãåã®ãã£ããã¢ããªã±ãŒã·ã§ã³ãå®è£ ããŸããã¯ã©ã€ã¢ã³ãã¯ãã£ãããµãŒããŒã«æ¥ç¶ããèªåã®ã¡ãã»ãŒãžãéä¿¡ããŸããã¯ã©ã€ã¢ã³ãã¯æšæºå ¥åãããŠãŒã¶ãŒã¡ãã»ãŒãžãèªã¿åããããããµãŒããŒãžéä¿¡ããŸãããã£ãããµãŒããŒã¯ãåä¿¡ããåã¡ãã»ãŒãžããã¹ãŠã®ã¯ã©ã€ã¢ã³ãã«ãããŒããã£ã¹ãããŸãã
ãã®ããã«ããµãŒããŒåŽã§ã¯ ãããŒããã£ã¹ããã£ãã« ã䜿çšããã¯ã©ã€ã¢ã³ããšãµãŒããŒéã®éä¿¡ã«ã¯ tokio_websockets ã䜿çšããŸãã
æ°ãã Cargo ãããžã§ã¯ããäœæããæ¬¡ã®äŸåé¢ä¿ã远å ããŠãã ããã
Cargo.toml:
[package]
name = "chat-async"
version = "0.1.0"
edition = "2024"
[dependencies]
futures-util = { version = "0.3.32", features = ["sink"] }
http = "1.4.0"
tokio = { version = "1.52.1", features = ["full"] }
tokio-websockets = { version = "0.13.2", features = ["client", "fastrand", "server", "sha1_smol"] }
å¿ èŠãª API
tokio ãš tokio_websockets ããæ¬¡ã®é¢æ°ãå¿
èŠã«ãªããŸããæéããã㊠API ã«æ
£ããŠãããŠãã ããã
WebSocketStreamã«å®è£ ãããŠãã StreamExt::next(): WebSocket ã¹ããªãŒã ããã¡ãã»ãŒãžãéåæã«èªã¿åããããWebSocketStreamã«å®è£ ãããŠãã SinkExt::send(): WebSocket ã¹ããªãŒã äžã§ã¡ãã»ãŒãžãéåæã«éä¿¡ããããã- Lines::next_line(): æšæºå ¥åãããŠãŒã¶ãŒã¡ãã»ãŒãžãéåæã«èªã¿åãããã
- Sender::subscribe(): ãããŒããã£ã¹ããã£ãã«ã賌èªããããã
2 ã€ã®ãã€ããª
éåžžãCargo ãããžã§ã¯ãã§ã¯ 1 ã€ã®ãã€ããªãš 1 ã€ã® src/main.rs ãã¡ã€ã«ããæãŠãŸããããã®ãããžã§ã¯ãã§ã¯ã2 ã€ã®ãã€ããªãå¿
èŠã§ãã1 ã€ã¯ã¯ã©ã€ã¢ã³ãçšããã 1 ã€ã¯ãµãŒããŒçšã§ãããããã 2 ã€ã®å¥ã
ã® Cargo ãããžã§ã¯ãã«ããããšãã§ããŸãããããã§ã¯ 2 ã€ã®ãã€ããªãæã€ 1 ã€ã® Cargo ãããžã§ã¯ãã«ãŸãšããŸãããããæ©èœãããã«ã¯ãã¯ã©ã€ã¢ã³ããšãµãŒããŒã®ã³ãŒãã src/bin ã®äžã«çœ®ãå¿
èŠããããŸãïŒããã¥ã¡ã³ã ãåç
§ïŒã
次ã®ãµãŒããŒã³ãŒããšã¯ã©ã€ã¢ã³ãã³ãŒããããããã src/bin/server.rs ãš src/bin/client.rs ã«ã³ããŒããŠãã ãããããªãã®ã¿ã¹ã¯ã¯ã以äžã®èª¬æã«åŸã£ãŠãããã®ãã¡ã€ã«ã宿ãããããšã§ãã
src/bin/server.rs:
// Copyright 2024 Google LLC // SPDX-License-Identifier: Apache-2.0 use futures_util::sink::SinkExt; use futures_util::stream::StreamExt; use std::error::Error; use std::net::SocketAddr; use tokio::net::{TcpListener, TcpStream}; use tokio::sync::broadcast::{Sender, channel}; use tokio_websockets::{Message, ServerBuilder, WebSocketStream}; async fn handle_connection( addr: SocketAddr, mut ws_stream: WebSocketStream<TcpStream>, bcast_tx: Sender<String>, ) -> Result<(), Box<dyn Error + Send + Sync>> { // TODO: ãã³ãã«ã€ããŠã¯ã以äžã®ã¿ã¹ã¯ã®èª¬æãåç §ããŠãã ããã } #[tokio::main] async fn main() -> Result<(), Box<dyn Error + Send + Sync>> { let (bcast_tx, _) = channel(16); let listener = TcpListener::bind("127.0.0.1:2000").await?; println!("listening on port 2000"); loop { let (socket, addr) = listener.accept().await?; println!("New connection from {addr:?}"); let bcast_tx = bcast_tx.clone(); tokio::spawn(async move { // Wrap the raw TCP stream into a websocket. let (_req, ws_stream) = ServerBuilder::new().accept(socket).await?; handle_connection(addr, ws_stream, bcast_tx).await }); } }
src/bin/client.rs:
// Copyright 2024 Google LLC // SPDX-License-Identifier: Apache-2.0 use futures_util::SinkExt; use futures_util::stream::StreamExt; use http::Uri; use tokio::io::{AsyncBufReadExt, BufReader}; use tokio_websockets::{ClientBuilder, Message}; #[tokio::main] async fn main() -> Result<(), tokio_websockets::Error> { let (mut ws_stream, _) = ClientBuilder::from_uri(Uri::from_static("ws://127.0.0.1:2000")) .connect() .await?; let stdin = tokio::io::stdin(); let mut stdin = BufReader::new(stdin).lines(); // TODO: ãã³ãã«ã€ããŠã¯ã以äžã®ã¿ã¹ã¯ã®èª¬æãåç §ããŠãã ããã }
ãã€ããªã®å®è¡
ãµãŒããŒã¯æ¬¡ã®ããã«å®è¡ããŸãã
cargo run --bin server
ã¯ã©ã€ã¢ã³ãã¯æ¬¡ã®ããã«å®è¡ããŸãã
cargo run --bin client
ã¿ã¹ã¯
src/bin/server.rsã®handle_connection颿°ãå®è£ ããŠãã ããã- ãã³ã:
tokio::select!ã䜿ã£ãŠãç¶ç¶çãªã«ãŒãå ã§ 2 ã€ã®ã¿ã¹ã¯ã䞊è¡ããŠå®è¡ããŸãã1 ã€ã®ã¿ã¹ã¯ã¯ã¯ã©ã€ã¢ã³ãããã¡ãã»ãŒãžãåä¿¡ããŠãããŒããã£ã¹ãããŸãããã 1 ã€ã¯ãµãŒããŒãåä¿¡ããã¡ãã»ãŒãžãã¯ã©ã€ã¢ã³ããžéä¿¡ããŸãã
- ãã³ã:
src/bin/client.rsã® main 颿°ã宿ãããŠãã ããã- ãã³ã: ãããŸã§ãšåæ§ã«ã
tokio::select!ãç¶ç¶çãªã«ãŒãå ã§äœ¿ã£ãŠ 2 ã€ã®ã¿ã¹ã¯ã䞊è¡ããŠå®è¡ããŸã: (1) æšæºå ¥åãããŠãŒã¶ãŒã¡ãã»ãŒãžãèªã¿åã£ãŠãµãŒããŒãžéä¿¡ããããšã(2) ãµãŒããŒããã¡ãã»ãŒãžãåä¿¡ããŠãŠãŒã¶ãŒã«è¡šç€ºããããšã
- ãã³ã: ãããŸã§ãšåæ§ã«ã
- ä»»æ: å®äºããããã¡ãã»ãŒãžã®éä¿¡è 以å€ã®ãã¹ãŠã®ã¯ã©ã€ã¢ã³ãã«ã¡ãã»ãŒãžããããŒããã£ã¹ãããããã«ã³ãŒãã倿ŽããŠãã ããã
è§£ç
é£äºããå²åŠè â Async
// èäœæš© 2024 Google LLC // SPDX-License-Identifier: Apache-2.0 use std::sync::Arc; use tokio::sync::{Mutex, mpsc}; use tokio::time; struct Chopstick; struct Philosopher { name: String, left_chopstick: Arc<Mutex<Chopstick>>, right_chopstick: Arc<Mutex<Chopstick>>, thoughts: mpsc::Sender<String>, } impl Philosopher { async fn think(&self) { self.thoughts .send(format!("Eureka! {} has a new idea!", &self.name)) .await .unwrap(); } async fn eat(&self) { // Keep trying until we have both chopsticks // Pick up chopsticks... let _left_chopstick = self.left_chopstick.lock().await; let _right_chopstick = self.right_chopstick.lock().await; println!("{} is eating...", &self.name); time::sleep(time::Duration::from_millis(5)).await; // The locks are dropped here } } // tokio scheduler doesn't deadlock with 5 philosophers, so have 2. static PHILOSOPHERS: &[&str] = &["Socrates", "Hypatia"]; #[tokio::main] async fn main() { // Create chopsticks let mut chopsticks = vec![]; PHILOSOPHERS .iter() .for_each(|_| chopsticks.push(Arc::new(Mutex::new(Chopstick)))); // Create philosophers let (philosophers, mut rx) = { let mut philosophers = vec![]; let (tx, rx) = mpsc::channel(10); for (i, name) in PHILOSOPHERS.iter().enumerate() { let mut left_chopstick = Arc::clone(&chopsticks[i]); let mut right_chopstick = Arc::clone(&chopsticks[(i + 1) % PHILOSOPHERS.len()]); if i == PHILOSOPHERS.len() - 1 { std::mem::swap(&mut left_chopstick, &mut right_chopstick); } philosophers.push(Philosopher { name: name.to_string(), left_chopstick, right_chopstick, thoughts: tx.clone(), }); } (philosophers, rx) // tx is dropped here, so we don't need to explicitly drop it later }; // Make them think and eat for phil in philosophers { tokio::spawn(async move { for _ in 0..100 { phil.think().await; phil.eat().await; } }); } // Output their thoughts while let Some(thought) = rx.recv().await { println!("Here is a thought: {thought}"); } }
ãããŒããã£ã¹ã ãã£ãã ã¢ããªã±ãŒã·ã§ã³
src/bin/server.rs:
// èäœæš© 2024 Google LLC // SPDX-License-Identifier: Apache-2.0 use futures_util::sink::SinkExt; use futures_util::stream::StreamExt; use std::error::Error; use std::net::SocketAddr; use tokio::net::{TcpListener, TcpStream}; use tokio::sync::broadcast::{Sender, channel}; use tokio_websockets::{Message, ServerBuilder, WebSocketStream}; async fn handle_connection( addr: SocketAddr, mut ws_stream: WebSocketStream<TcpStream>, bcast_tx: Sender<String>, ) -> Result<(), Box<dyn Error + Send + Sync>> { ws_stream .send(Message::text("Welcome to chat! Type a message".to_string())) .await?; let mut bcast_rx = bcast_tx.subscribe(); // A continuous loop for concurrently performing two tasks: (1) receiving // messages from `ws_stream` and broadcasting them, and (2) receiving // messages on `bcast_rx` and sending them to the client. loop { tokio::select! { incoming = ws_stream.next() => { match incoming { Some(Ok(msg)) => { if let Some(text) = msg.as_text() { println!("From client {addr:?} {text:?}"); bcast_tx.send(text.into())?; } } Some(Err(err)) => return Err(err.into()), None => return Ok(()), } } msg = bcast_rx.recv() => { ws_stream.send(Message::text(msg?)).await?; } } } } #[tokio::main] async fn main() -> Result<(), Box<dyn Error + Send + Sync>> { let (bcast_tx, _) = channel(16); let listener = TcpListener::bind("127.0.0.1:2000").await?; println!("listening on port 2000"); loop { let (socket, addr) = listener.accept().await?; println!("New connection from {addr:?}"); let bcast_tx = bcast_tx.clone(); tokio::spawn(async move { // Wrap the raw TCP stream into a websocket. let (_req, ws_stream) = ServerBuilder::new().accept(socket).await?; handle_connection(addr, ws_stream, bcast_tx).await }); } }
src/bin/client.rs:
// èäœæš© 2024 Google LLC // SPDX-License-Identifier: Apache-2.0 use futures_util::SinkExt; use futures_util::stream::StreamExt; use http::Uri; use tokio::io::{AsyncBufReadExt, BufReader}; use tokio_websockets::{ClientBuilder, Message}; #[tokio::main] async fn main() -> Result<(), tokio_websockets::Error> { let (mut ws_stream, _) = ClientBuilder::from_uri(Uri::from_static("ws://127.0.0.1:2000")) .connect() .await?; let stdin = tokio::io::stdin(); let mut stdin = BufReader::new(stdin).lines(); // Continuous loop for concurrently sending and receiving messages. loop { tokio::select! { incoming = ws_stream.next() => { match incoming { Some(Ok(msg)) => { if let Some(text) = msg.as_text() { println!("From server: {}", text); } }, Some(Err(err)) => return Err(err), None => return Ok(()), } } res = stdin.next_line() => { match res { Ok(None) => return Ok(()), Ok(Some(line)) => ws_stream.send(Message::text(line.to_string())).await?, Err(err) => return Err(err.into()), } } } } }
ã€ãã£ãªããã£ãã¯ãªRustãžãããã
Rustã®åºç€ ã§ã¯ãRust ã®æ§æãšäžæ žæŠå¿µã玹ä»ããŸãããããããããã«äžæ©é²ã¿ãŸãããããžã§ã¯ãã§ Rust ã 广ç㫠䜿ãã«ã¯ã©ãããã°ããã®ã§ãããããã€ãã£ãªããã£ãã¯ãª Rust ãšã¯ã©ã®ãããªãã®ã§ããããã
ãã®ã³ãŒã¹ã«ã¯æç¢ºãªæ¹éããããŸããããã€ãã®ãã¿ãŒã³ãå§ããããã§ãªããã®ããã¯è·é¢ã眮ãããä¿ããŸãããšã¯ããããããžã§ã¯ãã«ãã£ãŠå¿ èŠã¯ç°ãªãããšãçè§£ããŠããŸããçããèªèº«ã®ãããžã§ã¯ãã®æèãå¶çŽã®äžã§ãååãªæ å ±ã«åºã¥ãã倿ãã§ãããããå¿ èŠãªæ å ±ã¯åžžã«æäŸããŸãã
â ïž ãã®ã³ãŒã¹ã¯çŸåšã掻çºã«éçºäžã§ãã
å 容ã¯é »ç¹ã«å€ããå¯èœæ§ãããããŸã èŠã€ãã£ãŠããªã誀ããå«ãŸããŠãããããããŸãããããã§ãããã²ã²ãšãšããç®ãéããæ©ãæ®µéã§ãã£ãŒãããã¯ããå¯ããã ããïŒ
ã¹ã±ãžã¥ãŒã«
session outline
ãã®ã³ãŒã¹ã§ã¯ã以äžã«æãããããã¯ãæ±ããŸããåãããã¯ã¯ããã®è€éããé¢é£æ§ã«å¿ããŠã1æãŸãã¯è€æ°æã®ã¹ã©ã€ãã§æ±ããŸãã
察象èªè
CãC++11 以éãJava 7 以éãPython 2 ãŸã㯠3ãGoããããã¯åæ§ã®åœä»€åããã°ã©ãã³ã°èšèªã§ãå°ãªããšã 2ã3 幎ã®ã³ãŒãã£ã³ã°çµéšããããšã³ãžãã¢ã察象ãšããŠããŸããSwiftãKotlinãC#ãTypeScript ã®ãããªãããã¢ãã³ã§æ©èœè±å¯ãªèšèªã®çµéšã¯åæãšããŸããã
APIèšèšã®åºç€
- é»éåŸ: åŒã³åºãç®æã§ã®æçããšèªã¿ããããæåªå ããã人ã¯ãåŒã³åºããã颿°ã®å®£èšãèªãããããåŒã³åºãç®æãèªãã»ãã«ãã£ãšå€ãã®æéãè²»ããã
- APIãäºæž¬å¯èœã«ãã
- åœåèŠåã«åŸãïŒå€§æåã»å°æåã®èŠçŽã«åŸããæšæºã©ã€ãã©ãªã§ãã§ã«å äŸã®ããèªåœãåªå ãããããšãã°ãã¡ãœããå㯠âpush_backâ ã§ã¯ãªã âpushâãâemptyâ ã§ã¯ãªã âis_emptyâ ãªã©ã«ããïŒ
- æšæºã©ã€ãã©ãªã®èªåœåããã¬ã€ããçè§£ããAPIã§ãããã䜿ããäœããåºæ¬çãªåãã¢ã«ãŽãªãºã ã®ããã«æãããªãããŸãæšæºã©ã€ãã©ãªã確èªããã
- ãã®è¬çŸ©ã®åŸåã§æ±ããååã«ç¢ºç«ãããAPIèšèšãã¿ãŒã³ã䜿ãïŒäŸ: newtypeãææå/ãã¥ãŒåã®ãã¢ããšã©ãŒãã³ããªã³ã°ïŒ
- æå³ãããå®çšçãªããã¥ã¡ã³ãã³ã¡ã³ããæžãïŒäŸ: ã¢ã³ããŒã¹ã³ã¢ã空çœã«çœ®ãæããŠã¡ãœããåããã ç¹°ãè¿ãã ãã«ããªãããã¹ãŠã® markdown ã¿ã°ãåããããã ãã«åãæ å ±ãç¹°ãè¿ããªãã䜿çšäŸã瀺ãïŒ
åã·ã¹ãã ãæŽ»çšãã
- enumãstructãåãšã€ãªã¢ã¹ã®ç°¡åãªãããã
- newtype ãã¿ãŒã³ãšã«ãã»ã«å: æ€èšŒããã®ã§ã¯ãªããããŒã¹ãã
- æ¡åŒµãã¬ã€ã: 远å ã®æ¯ãèããæäŸãããã ããªã newtype ãã¿ãŒã³ã¯é¿ãã
- RAIIãã¹ã³ãŒãã¬ãŒããdrop bomb:
Dropã䜿ã£ãŠãªãœãŒã¹ãã¯ãªãŒã³ã¢ããããã¢ã¯ã·ã§ã³ãçºç«ãããäžå€æ¡ä»¶ã匷å¶ãã - ãããŒã¯ã³ãå: ç¹å®ã®æäœãå®è¡ããããšããŠãŒã¶ãŒã«èšŒæããã
- typestate ãã¿ãŒã³: æ£ããç¶æ é·ç§»ãã³ã³ãã€ã«æã«åŒ·å¶ãã
- åçšãã§ãã«ãŒã䜿ã£ãŠãã¡ã¢ãªæææš©ãšã¯ç¡é¢ä¿ãªäžå€æ¡ä»¶ã匷å¶ãã
- æšæºã©ã€ãã©ãªã® OwnedFd/BorrowedFd
- ãã©ã³ãä»ãå
åçšãã§ãã«ãŒãšæŠããªã
- ãææãåãšããã¥ãŒãå:
&strãšStringãPathãšPathBufãªã© - æææš©ã®èŠä»¶ãé ããªã: é ãã
.clone()ãé¿ããCowãæŽ»çšãã - æææš©ã®å¢çã«æ²¿ã£ãŠåãåå²ãã
- æææš©ã®éå±€ãæšæ§é ã®ããã«èšèšãã
- 埪ç°äŸåã管çããæŠç¥: åç §ã«ãŠã³ããåç §ã®ä»£ããã«ã€ã³ããã¯ã¹ã䜿ã
- å éšå¯å€æ§ïŒCellãRefCellïŒ
- ãŠãŒã¶ãŒå®çŸ©ããŒã¿åã®ã©ã€ãã¿ã€ã ãã©ã¡ãŒã¿ãæ±ã
Rustã«ãããããªã¢ãŒãã£ãºã
- ãã¬ã€ããšãžã§ããªãã¯é¢æ°ã®ç°¡åãªãããã
- Rustã«ã¯ç¶æ¿ããªã: ãã®æå³ãããšããã¯äœãïŒ
- ããªã¢ãŒãã£ãºã ã« enum ã䜿ã
- ããªã¢ãŒãã£ãºã ã«ãã¬ã€ãã䜿ã
- ã³ã³ããžã·ã§ã³ã䜿ã
- æãé©åãªãã¿ãŒã³ã¯ã©ãéžã¹ã°ãããïŒ
- ãžã§ããªã¯ã¹ãæ±ã
- åŒæ°ãšããŠäœ¿ããªãã颿°ã®ãžã§ããªãã¯åãã©ã¡ãŒã¿ã«ããã¹ããããããšããã¬ã€ããªããžã§ã¯ãã«ããã¹ããïŒ
- ãã¬ã€ãå¢çã¯ãžã§ããªãã¯ãã©ã¡ãŒã¿ãåç §ããŠããå¿ èŠã¯ãªã
- ãã¬ã€ãã«ãããåãã©ã¡ãŒã¿: ãžã§ããªãã¯ãã©ã¡ãŒã¿ã«ããã¹ãããé¢é£åã«ããã¹ããïŒ
- ãã¯ã: ãã¬ã€ãã ãã§ã¯äžååãªïŒãããã¯è€éãããïŒãšãã«ãã³ãŒããDRYã«ä¿ã€ããã®æçšãªããŒã«
ãšã©ãŒãã³ããªã³ã°
- ãšã©ãŒã®ç®çã¯äœãïŒ å埩ããå ±åãã
- Result ãš Option
- è¯ããšã©ãŒãèšèšãã:
- ãšã©ãŒã®ã¹ã³ãŒããå®ããã
- ãšã©ãŒãäžäœãžäŒæããã¹ã³ãŒãã®å¢çããŸããéã«ã远å ã®ã³ã³ããã¹ããä¿æããã
Errorãã¬ã€ããæŽ»çšããŠãå®å šãªãšã©ãŒãã§ãŒã³ã远跡ãããthiserrorãæŽ»çšããŠããšã©ãŒåå®çŸ©æã®ãã€ã©ãŒãã¬ãŒããæžãããanyhow
Result<Result<T, RecoverableError>, FatalError>ã䜿ã£ãŠãèŽåœçãªãšã©ãŒãšå埩å¯èœãªãšã©ãŒãåºå¥ããã
API èšèšã®åºç€
segment outline
æå³ã®ããããã¥ã¡ã³ãã³ã¡ã³ã
// Copyright 2025 Google LLC // SPDX-License-Identifier: Apache-2.0 /// ã¯ã©ã€ã¢ã³ãåã API // â 詳现ãäžè¶³ããŠããŸã pub mod client {} /// A ãã B ãžã®é¢æ° // â åé·ã§ã fn a_to_b(a: A) -> B {...} /// ããŒã¿ããŒã¹ã«æ¥ç¶ããŸãã // â 詳现ãäžè¶³ããŠããŸã fn connect() -> Result<(), Error> {...}
-
ããã¥ã¡ã³ãã³ã¡ã³ãã¯ãéçºè ãæãããæ¥ããããã¥ã¡ã³ã圢åŒã§ãã
-
åªããããã¥ã¡ã³ãã³ã¡ã³ãã¯ãæãããªæ å ±ãèšãæããããšãªãã ã³ãŒããååãåã ãã§ã¯äŒããããªãæ å ±ãæäŸããŸãã
誰ã«åããŠæžããŠããŸããïŒ
ååãååè ãæ®æ®µã¯ã»ãšãã©å£°ãäžããªã API ãŠãŒã¶ãŒããããšãèªåèªèº«ã§ããïŒ
// Copyright 2025 Google LLC // SPDX-License-Identifier: Apache-2.0 // å°éå®¶ã¯å°éå®¶ã«åããŠæžã /// åçšãã§ãã«ãŒã®ããã« MIR ãæ£æºåããŸãã /// /// ãã®ãã¹ã¯ãMIR ãã LLVM-IR ãžã®å€æã«é²ãåã«ã /// ãã¹ãŠã®åçšã NLL-Polonius ã®å¶çŽã«é©åããããšãä¿èšŒããŸãã pub fn canonicalize_mir(mir: &mut Mir) { // ... } // å°éå®¶ã¯ååŠè ã«åããŠæžã /// åçšãã§ãã¯ã«åããŠäžéã¬ãã« IRïŒMIRïŒãæºåããŸãã /// /// åçšãã§ãã«ãŒã¯ãåçŽåããããæ£æºã圢åŒã® MIR ã察象ã«åäœããŸãã /// ãã®é¢æ°ã¯ãã®å€æãè¡ããŸããããã¯ãã³ãŒãçæã® /// æçµæ®µéã«é²ãããã®åææ¡ä»¶ã§ãã /// /// Rust ã®äžé衚çŸã«ã€ããŠè©³ããã¯ã /// [rustc-dev-guide](https://rustc-dev-guide.rust-lang.org/mir/index.html) ãåç §ããŠãã ããã pub fn canonicalize_mir(mir: &mut Mir) { // ... }
-
èæ¯: ç¥èã®åªã ãšã¯ã å°éå®¶ãä»è ãèªåãšåãã¬ãã«ã®å°éç¥èãšèŠç¹ãæã£ãŠãããš æ³å®ããŠããŸãèªç¥ãã€ã¢ã¹ã§ãã
-
åæ©: èªè ã¯ãããªããšåãã¬ãã«ã®å°éç¥èãåã èŠç¹ãæã£ãŠããããã§ã¯ãããŸãããèªåã®ãããªäººã«åããŠæžãã®ã§ã¯ãªãã ä»è ã«åããŠæžããŠãã ããã
-
æå³ããèªåã«åããŠæžããŠããŸããšãäŒãããèŠç¹ã 説æãããæŠå¿µãçžæã«çè§£ãããªãåå ã«ãªããŸãã
-
ããã¥ã¡ã³ããèªãã§ããäžã§å®çšçãªæ å ±ãèŠã€ããããã«èŠåŽããŠããã èªåèªèº«ã®éå»ã®å§¿ãããããŸã§ã«èŠãŠãã誰ããæãæµ®ãã¹ãŠãã ããã
ã³ãŒãããŒã¹ã®ã©ã®é åã« doc comment ã®æåœãŠãå¿ èŠããèãããšãã¯ããããã人ç©åã念é ã«çœ®ããŠãã ããã
-
誰ã«åããŠæžããŠããŸããïŒ
-
åããã©ãé·å€§ãª doc comment ã®äžããéèŠãªè©³çްãèŠã€ããããã« èŠåŽããŠãããèªåèªèº«ã®éå»ã®å§¿ãããããŸã§ã«èŠãŠãã誰ããæãæµ®ãã¹ãŠãã ããã æ å ±ãè©°ã蟌ã¿ãããªãã§ãã ããã
-
åžžã«åããããŠãã ãã: ãã®ããã¥ã¡ã³ã㯠API ãŠãŒã¶ãŒã«ãšã£ãŠ çè§£ã®åŠšãã«ãªã£ãŠããªãããå¿ èŠãªããšãçŽ æ©ãææ¡ã§ãããã ãããã¯å¿ èŠãªæ å ±ãã©ãã«ããããèŠã€ãããããã
-
åžžã«èæ ®ããŠãã ãã: API ã¬ãã«ã®ããã¥ã¡ã³ãã¯å°éå®¶ãèªã¿ãŸããdoc comment 㯠èªè ã«ãã®åéã®åºç€ãæããã®ã«é©ããå Žæã§ã¯ãªããããããŸããããã®å Žåã¯ã åç §å ã瀺ããååãæããŠãã ããã詳ããé·æã®ããã¥ã¡ã³ããžèªå°ããŸãããã
ã©ã€ãã©ãªãšã¢ããªã±ãŒã·ã§ã³ã®ããã¥ã¡ã³ã
åºæ¬ç㪠API ã«ã€ããŠãååãåã·ã°ããã£ãç¹°ãè¿ããããªã詳现㪠ããã¥ã¡ã³ããç®ã«ããããšããããããããŸãããå®å®ããŠããŠåå©çšæ§ã®é«ã ã³ãŒãã§ããã°ãååãªæè³å¯Ÿå¹æãèŠèŸŒãã§ãããå¯èœã§ãã
-
ã©ã€ãã©ãªã³ãŒã:
- ãŠãŒã¶ãŒæ°ãå€ãã
- é¢é£ããå¹ åºãåé¡ã解決ããã
- API ãå®å®ããŠããããšãå€ãã
-
ã¢ããªã±ãŒã·ã§ã³ã³ãŒãã¯ãã®éã§ã:
- ãŠãŒã¶ãŒãå°ãªãã
- ç¹å®ã®åé¡ã解決ããã
- 倿Žãé »ç¹ã«å ¥ãã
-
ã³ãŒããç¹°ãè¿ããåã API ãå€ãã®äŸãã±ãŒã¹ã¹ã¿ãã£ãšãšãã« äœåºŠãåãäžãããããªã詳现ãªããã¥ã¡ã³ããèŠãããšããããããããŸããã æèãéèŠã§ãã誰ãã誰ã®ããã«æžããã®ããã©ã®ãããªé¡æãæ±ã£ãŠããã®ãã ãããŠã©ã®ãããªãªãœãŒã¹ãæã£ãŠããã®ãããšããããšã§ãã
-
åºæ¬çãªã©ã€ãã©ãªã³ãŒãã«ã¯ã詳现ãªããã¥ã¡ã³ããä»ãããšããããããŸãã ããšãã°ãæšæºã©ã€ãã©ãªããSerde ã Tokio ã®ãããªåå©çšæ§ã®é«ã ãã¬ãŒã ã¯ãŒã¯ã§ãããã®ã³ãŒããæ åœããããŒã ã¯ãå€ãã®å Žåããã®ãã㪠詳现ãªããã¥ã¡ã³ããæžããŠç¶æããããã®é©åãªãªãœãŒã¹ãæã£ãŠããŸãã
-
ã©ã€ãã©ãªã³ãŒãã¯å®å®ããŠããããšãå€ããããæçŽããå¿ èŠã«ãªããŸã§ã«ã ã³ãã¥ããã£ã¯è©³çްãªããã¥ã¡ã³ããã倧ããªæ©æµãåŒãåºããŸãã
-
ã¢ããªã±ãŒã·ã§ã³ã³ãŒãã¯éã®ç¹æ§ãæã£ãŠããŸãããŠãŒã¶ãŒã¯å°ãªãã ç¹å®ã®åé¡ã解決ããé »ç¹ã«å€åããŸããã¢ããªã±ãŒã·ã§ã³ã³ãŒãã§ã¯ã 詳现ãªããã¥ã¡ã³ãã¯ããã«å€ããªãã誀解ãæããã®ã«ãªããŸãããŸãã ææ°ã®ç¶æ ã«ä¿ãããŠããéã§ãããå®åçãªããã¥ã¡ã³ãããåå㪠æè³å¯Ÿå¹æãåŸãã®ã¯é£ããã§ãããŠãŒã¶ãŒãå°ãªãããã§ãã
ããã¥ã¡ã³ãã³ã¡ã³ãã®æ§é
- ç°¡æœãª1æã®èŠçŽã
- ãã詳现ãªèª¬æã
- ç¹å¥ãªã»ã¯ã·ã§ã³: ã³ãŒãäŸããããã¯ããšã©ãŒãå®å šæ§ã®åææ¡ä»¶ã
// Copyright 2025 Google LLC // SPDX-License-Identifier: Apache-2.0 /// æååããããŒãšå€ã®ãã¢ãããŒã¹ããŸãã /// /// å ¥åæåå㯠`key=value` ã®åœ¢åŒã§ãªããã°ãªããŸãããæåã® '=' ããå㯠/// ããŒãšããŠæ±ããããã以éã¯å€ãšããŠæ±ãããŸãã /// /// # Examples /// /// ``` /// use my_crate::parse_key_value; /// let (key, value) = parse_key_value("lang=rust").unwrap(); /// assert_eq!(key, "lang"); /// assert_eq!(value, "rust"); /// ``` /// /// # Panics /// /// å ¥åã空ã®å Žåã«ãããã¯ããŸãã /// /// # Errors /// /// æååã« `=` ãå«ãŸããŠããªãå Žå㯠`ParseError::Malformed` ãè¿ããŸãã /// /// # Safety /// /// ...ã®å Žåãæªå®çŸ©åäœãåŒãèµ·ãããŸãã unsafe fn parse_key_value(s: &str) -> Result<(String, String), ParseError> enum ParseError { Empty, Malformed, }
-
Rust ã§æ £çšçãªããã¥ã¡ã³ãã³ã¡ã³ãã¯ãéçºè ãèªã¿ããããããæ £äŸçãªæ§é ã«åŸããŸãã
-
ããã¥ã¡ã³ãã³ã¡ã³ãã®æåã®è¡ã¯ã颿°ã1æã§èŠçŽãããã®ã§ããç°¡æœã«ä¿ã¡ãŸãããã
rustdocããã®ä»ã®ããŒã«ã¯ããã匷ãåæãšããŠãããã¢ãžã¥ãŒã«ã¬ãã«ã®ããã¥ã¡ã³ããæ€çŽ¢çµæã§ã¯çãèŠçŽãšããŠäœ¿ãããŸãã -
次ã«ããã®é¢æ°ã®ããªãããšãäœããã«ã€ããŠãè€æ°æ®µèœã«ãããé·ãã®èª¬æãèšèŒã§ããŸããMarkdown ã䜿ããŸãã
-
æåŸã«ããããã¬ãã«ã®ã»ã¯ã·ã§ã³èŠåºãã䜿ã£ãŠå å®¹ãæŽçã§ããŸããããã¥ã¡ã³ãã³ã¡ã³ãã§ã¯ã
# Examplesã# Panicsã# Errorsã# Safetyãã»ã¯ã·ã§ã³ã¿ã€ãã«ãšããŠãã䜿ãããŸããRust ã³ãã¥ããã£ã§ã¯ãAPI ã®é¢é£ããåŽé¢ããããã®ã»ã¯ã·ã§ã³ã§ææžåãããŠããããšãæåŸ ãããŠããŸãã -
Rust ã¯å®å šæ§ãšæ£ãããéåžžã«éèŠããŠããŸãããšã©ãŒæã®ã³ãŒãã®æåãææžåããããšã¯ãä¿¡é Œæ§ã®é«ããœãããŠã§ã¢ãæžãããã§äžå¯æ¬ ã§ãã
-
# Panics: 颿°ããããã¯ããå¯èœæ§ãããå Žåã¯ããããèµ·ããããå ·äœçãªæ¡ä»¶ãå¿ ãææžåããªããã°ãªããŸãããåŒã³åºãåŽã¯äœãé¿ããã¹ãããç¥ãå¿ èŠããããŸãã-
質å:
Resultãè¿ãããšã奜ãèšèªã§ããªããããã¯ã®ææžåãããã»ã©éèŠãªã®ããã¯ã©ã¹ã«åããããŠãã ããã -
åç: ãããã¯ã¯ãå埩äžèœãªããã°ã©ãã³ã°ãšã©ãŒã®ããã®ãã®ã§ããåŒã³åºãåŽã«ãã£ãŠå¥çŽãç Žãããå Žåãé€ããã©ã€ãã©ãªã¯ãããã¯ãã¹ãã§ã¯ãããŸããããããã®å¥çŽãææžåããããšã¯äžå¯æ¬ ã§ãã
-
-
# Errors:Resultãè¿ã颿°ã§ã¯ããã®ã»ã¯ã·ã§ã³ã§ã©ã®ãããªçš®é¡ã®ãšã©ãŒããã©ã®ãããªç¶æ³ã§çºçããããã説æããŸããåŒã³åºãåŽã¯ãå ç¢ãªãšã©ãŒãã³ããªã³ã°ããžãã¯ãæžãããã«ãã®æ å ±ãå¿ èŠãšããŸãã -
# Safetyã³ã¡ã³ãã§ã¯ãunsafe 颿°ã«å¯ŸããŠæºãããªããã°ãªããªãå®å šæ§ã®åææ¡ä»¶ãææžåããŸããããããªããšãæªå®çŸ©åäœãçºçããå¯èœæ§ããããŸããããã«ã€ããŠã¯ Unsafe Rust ã®ãã£ãŒããã€ãã§è©³ããæ±ããŸãã
ããŒã¯ãŒããæãããããã¯ãžã®éããã¹ã瀺ã
// Copyright 2025 Google LLC // SPDX-License-Identifier: Apache-2.0 /// [MARC 21 ã¬ã³ãŒããªãŒããŒ][leader]ã®ããŒã¹æžã¿è¡šçŸã /// /// MARC ãªãŒããŒã«ã¯ãã¬ã³ãŒãã®æ®ãã®éšåãã©ã®ããã«è§£éããããèŠå® /// ããã¡ã¿ããŒã¿ãå«ãŸããŸãã /// /// [leader]: https://www.loc.gov/marc/bibliographic/bdleader.html pub struct Leader { /// ã¹ããŒããšããã®åŸã«ç¶ãæå¹ãªããŒã¿ãã£ãŒã«ãã®éåãæ±ºå®ããŸãã /// /// ãªãŒããŒã® byte 6 ã«ãšã³ã³ãŒããããŠããŸãã pub type_of_record: char, /// ãã倧ããªèäœç©å ã®èšäºã«å¯Ÿãã "773 Host /// Item Entry" ã®ãããªé¢é£ãã£ãŒã«ããããŒã¹ãããã©ããã瀺ããŸãã /// /// ãªãŒããŒã® byte 7 ã«ãšã³ã³ãŒããããŠããŸãã pub bibliographic_level: char, // ... ãã®ä»ã®ãã£ãŒã«ã } /// [MARC 21 ã¬ã³ãŒããªãŒããŒ][leader]ãããŒã¹ããŸãã /// /// ãªãŒããŒã¯åºå®é·ã® 24 ãã€ãã®ãã£ãŒã«ããšããŠãšã³ã³ãŒããããŠããã /// ã¬ã³ãŒãã®æ®ãã®éšåã®æå³çãªè§£éãæ±ºå®ããã¡ã¿ããŒã¿ãå«ã¿ãŸãã /// /// [leader]: https://www.loc.gov/marc/bibliographic/bdleader.html pub fn parse_leader(leader_bytes: &[u8; 24]) -> Result<Leader, MarcError> { todo!() } #[derive(Debug)] pub enum MarcError {}
-
åæ©: ããã¥ã¡ã³ãã®èªè ã¯ã奜ããªå°èª¬ã®äŒè©±æãèªãããã«ãããªãã® doc comment ã®å€§åã粟èªããããã§ã¯ãããŸããã
ãŠãŒã¶ãŒã¯ãããŠãããã®å Žã§è§£æ±ºããããšããŠããåé¡ã«é¢ä¿ãã ããã¥ã¡ã³ãã®ç®æãèŠã€ããããã«ããã£ãšèªã¿ãæŸãèªã¿ããŸãã
èªåã«é¢ä¿ã®ããããŒã¯ãŒãããéããã¹ã«ãªããããªèªãèŠã€ãããšã ãŠãŒã¶ãŒã¯ææžåãããŠãã察象ã®ååŸã®æèãæ¢ãå§ããŸãã
-
ã¯ã©ã¹ã«è³ªå: ããã¥ã¡ã³ãã§ã¯äœãæ¢ããŸãã? ããã§ã¯ãäžè¬çã« ããã¥ã¡ã³ãã«æ±ãã䟡å€ã§ã¯ãªãããã®å Žãã®å Žã®æ å ±æ¢çŽ¢ã«æ³šç®ããŠãã ããã
-
ããŒã¯ãŒãã¯æ®µèœã®ãªãã¹ãåé ã§æããã
ããã¯ãã£ãšèªãããšãæŸãèªã¿ã®å©ãã«ãªããŸããæ®µèœã®æåã®æ°èªã æãç®ã«å ¥ããããããã§ãã
ãã£ãšèªãããšãæŸãèªã¿ã¯ããŠãŒã¶ãŒãããã¹ãå ãçŽ æ©ãç§»åããå©ãã« ãªããŸããããŒã¯ãŒããã§ããã ãæ®µèœã®åé è¿ãã«çœ®ãããšã§ãé¢é£æ å ± ãèŠã€ãããã©ãããããæ©ã倿ã§ããŸãã
-
éããã¹ã¯ç€ºãããã ã説æããããªãã
ãŠãŒã¶ãŒã API èšèšè ãšåããã¡ã€ã³ç¥èãæã£ãŠãããšã¯éããŸããã
æ¬çã§ã¯ãªãå°éçšèªãé åèªã«è§Šããå Žåã¯ãåå¿è ãããã«è¿œå 㧠調ã¹ãããã ãã®ååãªæèãæã¡èŸŒãããã«ããŠãã ããã
-
éããã¹ã®æç€ºã¯èªç¶ã«èµ·ããããšããããããŸããããšãã°ãããŸããŸãª ãããã³ã«ã«èšåãããããã¯ãŒãã³ã°ã©ã€ãã©ãªãèããŠã¿ãŠãã ããã ããããèªç¶ã«ãããªããªãå Žåã¯ãäœã«è§Šããã¹ãããéžã¶ã®ãé£ãã ãªããŸãã
çµéšå: API éçºè ã¯ãåå¿è ãèªåã®ææžåããŠãããã®ã«åºäŒã£ããã ã©ã®æ å ±æºã調ã¹ãã ãããããŸããçŽãããã誀ã£ãæãããã远ã£ãŠ ããŸãå¯èœæ§ã¯ããã ãããããšèªåãã¹ãã§ãã
ãŠãŒã¶ãŒã«ã¯ãèªåã§äž»é¡ã調ã¹ãããã ãã®ååãªæ å ±ãäžããã¹ãã§ãã
-
ãã§ã«æ±ã£ããåœåèŠåãå«ã API ã®äºæž¬å¯èœæ§ããéããã¹ã®äžåœ¢æ ã§ãã
åé·ããé¿ãã
ååãšåã·ã°ããã£ã¯å€ãã®æ å ±ãäŒããããããããã³ã¡ã³ãã§ç¹°ãè¿ããªãã§ãã ããã
// Copyright 2025 Google LLC // SPDX-License-Identifier: Apache-2.0 // åå/åã®æ å ±ãç¹°ãè¿ããŠãããçç¥ã§ããïŒ /// str ãã ipv4 ãè§£æããã倱æã¢ãŒãã«ã¯ option ãè¿ãã fn parse_ip_addr_v4(input: &str) -> Option<IpAddrV4> { ... } // ãã£ãŒã«ãåããæãããªæ å ±ãç¹°ãè¿ããŠãããçç¥ã§ããïŒ struct BusinessAsset { /// 顧客 idã customer_id: u64, } // æåã«ååã«èšåããŠãããããããªãããšïŒ /// `ServerSynchronizer` ã¯ããŒã«ã«ã®ç·šéãéä¿¡ãããªãŒã±ã¹ãã¬ãŒã¿ãŒã§ãã [...] struct ServerSynchronizer { ... } // ããè¯ãïŒç®çã«çŠç¹ãåœãŠãŠããã /// ããŒã«ã«ã®ç·šéãéä¿¡ãã [...] struct ServerSynchronizer { ... } // æåã«é¢æ°åã«èšåããŠãããããããªãããšïŒ /// `sync_to_server` ã¯ããŒã«ã«ã®ç·šéãéä¿¡ãã [...] fn sync_to_server(...) // ããè¯ãïŒé¢æ°ã«çŠç¹ãåœãŠãŠããã /// ããŒã«ã«ã®ç·šéãéä¿¡ãã [...] fn sync_to_server(...)
-
åæ©: åå/ã·ã°ããã£ã®æ å ±ãåã«ç¹°ãè¿ãã ãã®ããã¥ã¡ã³ãã¯ãAPI å©çšè ã«äœãæ°ããæ å ±ãæäŸããŸããã
ããã«ãã·ã°ããã£ã®æ å ±ã¯æéãšãšãã«å€ããå¯èœæ§ããããŸãããããã«åãããŠããã¥ã¡ã³ããæŽæ°ããããšã¯éããŸããã
-
ããã¯é¥ãããããã¿ãŒã³ã§ãïŒ
ãåžžã«ã³ãŒããããã¥ã¡ã³ãåããããšããå©èšã«å¯ŸããçŽ æŽãªã¢ãããŒãã§ã¯ããã®å©èšãæåã©ããã«åãåã£ãŠããŸãããã®æå³ã«ã¯åŸããŠããŸããã
äžéšã®ããŒã«ã¯ããã¥ã¡ã³ãã®ç¶²çŸ çã匷å¶ããããšããããŸããããã®çš®ã®ããã¥ã¡ã³ãã¯æè»œãªå¯ŸåŠã«ãªããã¡ã§ãã
-
ããã¥ã¡ã³ãã®ç°ãªãã¢ãŒãã®ç®çãæèããŠãã ããã
-
ã©ã€ãã©ãªã³ãŒãã¯ããããäœã®ããã«äœ¿ãããã®ãããã®ç¯å²ããããã䜿ãããšããŠãã人ã ã®å¹ åºããçè§£ãã圢ã§ããã¥ã¡ã³ãåããå¿ èŠããããŸãã
-
ã¢ããªã±ãŒã·ã§ã³ã³ãŒãã¯ç®çãããéå®çã§ããããããã£ãšåçŽã§çŽæ¥çã§ãåé¡ãããŸããã
-
-
ã¢ã€ãã ã®ååã¯ããã®ã¢ã€ãã ã®ããã¥ã¡ã³ãã®äžéšã§ãã
åæ§ã«ã颿°ã®ã·ã°ããã£ã¯ãã®é¢æ°ã®ããã¥ã¡ã³ãã®äžéšã§ãã
ãããã£ãŠãdoc comment ã®èšè¿°ãå§ããæç¹ã§ãã¢ã€ãã ã®ããã€ãã®åŽé¢ã¯ãã§ã«ã«ããŒãããŠããŸãã
é ç®ã䞊ã¹ãããšèªäœãç®çã«ãæ å ±ãç¹°ãè¿ããªãã§ãã ããã
-
æšæºã©ã€ãã©ãªã®å€ãã®é åã§ããã¥ã¡ã³ããæå°éãªã®ã¯ãååãšåã ãã§ååãªæ å ±ãåŸãããããã§ãã
çµéšå: å©çšè ã®èŠç¹ããèŠãŠãäœã®æ å ±ãäžè¶³ããŠããã§ãããããååãã·ã°ããã£ãå®è£ ã®ç¡é¢ä¿ãªè©³çް以å€ã§èããŠãã ããã
-
Rust ãæšæºã©ã€ãã©ãªã®åºæ¬äºé ã説æããªãã§ãã ãããèªè ã¯èšèªãã®ãã®ã«ã€ããŠäžçŽçšåºŠã®çè§£ãæã£ãŠãããšæ³å®ããŠãã ãããèªåã® API ã®ããã¥ã¡ã³ãåã«éäžããŠãã ããã
ããšãã°ã颿°ã
Resultãè¿ãå ŽåãResultãçå笊æŒç®åãã©ã®ããã«åäœãããã説æããå¿ èŠã¯ãããŸããã
ããã«è©³ãã
-
#![warn(missing_docs)]lint ã¯ãdoc comment ã®ååšã匷å¶ããã®ã«åœ¹ç«ã€ããšããããŸãããéçºè ã«å€§ããªè² æ ã課ãããã®çµæãšããŠãã®ãããªè³ªã®äœãã³ã¡ã³ããæžããã¿ãŒã³ã«å¯ããããåå ã«ãªãåŸãŸãããã®çš®ã® lint ã¯ããããžã§ã¯ãã®ä¿å®æ åœè ããã®èŠæ±ã«ç¶ç¶ããŠå¯Ÿå¿ã§ããå Žåã«ã®ã¿æå¹ã«ãã¹ãã§ãããéåžžã¯ã¢ããªã±ãŒã·ã§ã³ã³ãŒãã§ã¯ãªãã©ã€ãã©ãªã¹ã¿ã€ã«ã® crate ã«å¯ŸããŠã®ã¿æå¹ã«ãã¹ãã§ãã
ååãšã·ã°ããã£ã¯å®å šãªããã¥ã¡ã³ãã§ã¯ãªã
// Copyright 2025 Google LLC // SPDX-License-Identifier: Apache-2.0 // æªãäŸ /// æäœãå®äºãããšãã«è§£æ±ºããã future ãè¿ããŸãã fn sync_to_server() -> Future<Bool>; // è¯ãäŸ /// ããŒã«ã«ã®ç·šéå 容ããµãŒããŒã«éä¿¡ããŸããç«¶åããç·šéããã£ãå Žåã¯ã /// ããããäžæžãããŸãã fn sync_to_server() -> Future<Bool>; // æªãäŸ /// ã¡ãŒã«ã®éä¿¡ã«å€±æããå Žåã¯ãšã©ãŒãè¿ããŸãã fn send(&self, email: Email) -> Result<(), Error>; // è¯ãäŸ /// ã¡ãŒã«ãããã¯ã°ã©ãŠã³ãé ä¿¡ã®ããã«ãã¥ãŒã«å ¥ããããã«è¿ããŸãã /// /// ã¡ãŒã«ã®åœ¢åŒãäžæ£ãªå Žåã¯ãå³åº§ã«ãšã©ãŒãè¿ããŸãã fn send(&self, email: Email) -> Result<(), Error>;
-
åæ©: API èšèšè ã¯ã颿°åãšã·ã°ããã£ã ãã§ååãªããã¥ã¡ã³ãã«ãªããšããèãã«é床ã«ã³ãããããŠããŸãããšããããŸãã
-
ç¹°ãè¿ãã«ãªããŸãããååãšåã¯ããã¥ã¡ã³ãã® äžéš ã§ããåžžã«ããã ãã§å šäœåãèªããããã§ã¯ãããŸããã
-
颿°ã®ååããã©ã¡ãŒã¿åããŸãã¯ãã®é¢æ°ã®ã·ã°ããã£ã§ã¯ã«ããŒãããªã颿°ã®æ¯ãèããèããŠãã ããã
-
sync_to_server()ãäœããäžæžãããå¯èœæ§ãããããšïŒããŒã¿æå€±ã«ã€ãªããïŒã¯æçœã§ã¯ãªãããããããææžåããŸãã -
ã¡ãŒã«ã®äŸã§ã¯ããã®é¢æ°ãæåãè¿ããŠãã¡ãŒã«ã®é ä¿¡ã«ã¯å€±æããå¯èœæ§ãããããšã¯æçœã§ã¯ãããŸããã
-
-
ææ§ãããªããããã«ã³ã¡ã³ãã䜿ããŸãããã¥ã¢ã³ã¹ã®ããæ¯ãèãããAPI ã®å©çšè ãã€ãŸããå¯èœæ§ã®ããæ¯ãèãã¯ãææžåããã¹ãã§ãã
ãHowããšãWhereãã§ã¯ãªãããWhyããšãWhatã
é »ç¹ã«å€ããããç¡é¢ä¿ãªè©³çްãããã¥ã¡ã³ãåããã®ã¯é¿ããŠãã ããã
// Copyright 2025 Google LLC // SPDX-License-Identifier: Apache-2.0 // æªãäŸ /// `User` ã¬ã³ãŒãã Postgres ããŒã¿ããŒã¹ã«ä¿åããŸãã /// /// ãã®é¢æ°ã¯æ°ããæ¥ç¶ãéããŠãã©ã³ã¶ã¯ã·ã§ã³ãéå§ããŸããæå®ããã /// ID ãæã€ãŠãŒã¶ãŒãååšãããã `SELECT` ã¯ãšãªã§ç¢ºèªããŸãããŠãŒã¶ãŒã /// èŠã€ãããªãå Žåã¯ã`INSERT` ãå®è¡ããŸãã /// /// # ãšã©ãŒ /// /// ããããã®ããŒã¿ããŒã¹æäœã倱æããå Žåã¯ããšã©ãŒãè¿ããŸãã pub fn save_user(user: &User) -> Result<(), db::Error> { // ... } // è¯ãäŸ /// ãŠãŒã¶ãŒã¬ã³ãŒããã¢ãããã¯ã«ä¿åããŸãã /// /// # ãšã©ãŒ /// /// ãŠãŒã¶ãŒïŒããŒã¯ `user.username` ãã£ãŒã«ãïŒããã§ã«ååšããå Žåã¯ã /// `db::Error::DuplicateUsername` ãšã©ãŒãè¿ããŸãã pub fn save_user(user: &User) -> Result<(), db::Error> { // ... }
-
åæ©: ãŠãŒã¶ãŒãç¥ãããã®ã¯ãå®è£ ã®è©³çްã§ã¯ãªã API ã®å¥çŽ ïŒãã®é¢æ°ã«ã€ããŠäœãä¿èšŒããããïŒã§ãã
-
åæ©: å®è£ ã®è©³çްã説æããããã¥ã¡ã³ãã³ã¡ã³ãã¯ãå¥çŽã説æããã³ã¡ã³ã ãããæ©ãå€ããªããŸãã
å éšæ å ±ã¯ããŠãŒã¶ãŒã«ã¯é¢ä¿ãªãå¯èœæ§ãé«ãã§ãã颿°ã®ããã¥ã¡ã³ã ã³ã¡ã³ãã§ãåé¡ãè§£ãããã«
forã«ãŒãã䜿ã£ãŠãããšèª¬æãããšãããã ãã®æ å ±ã«äœã®æå³ãããã§ããããã -
å®è£ ã説æããå¿ èŠãããå ŽåããããããããŸããããããã¯ããããã ãã® API ã®å©çšè ã代ããã«èªèããŠããã¹ã广ãäžå€æ¡ä»¶ãããããã§ãã
å®è£ ã®è©³çްãã®ãã®ã§ã¯ãªãããããã®å¹æãäžå€æ¡ä»¶ã«çŠç¹ãåœãŠãŠãã ããã
ç¹°ãè¿ããŸããå®è£ ã®è©³çްã¯å€ããããã ãã§ãªãå®éã«å€ãããããããã㮠詳现ã¯èª¬æããªãã§ãã ããã
-
äœãã©ãã§äœ¿ãããŠãããã«ã€ããŠãè§Šããªãã§ãã ãããããããŸãããã® æ å ±ãããã«å€ããªãããå¥ã®äŸã§ãã
æŒç¿: 詳现ãããã察話
äžèŠãªè©³çްãããšãã«ã¯ãå®éã«ã¯ææžåãå¿ èŠãªäœãã瀺ã㊠ããããšããããŸãã
// Copyright 2025 Google LLC // SPDX-License-Identifier: Apache-2.0 /// ã¹ã©ã€ã¹ããœãŒãããŸããååž°çã¯ã€ãã¯ãœãŒãã䜿çšããŠå®è£ ãããŠããŸãã fn sort_quickly<T: Ord>(to_sort: &mut [T]) { ... }
-
åè¬è ã«å°ãã: ãã®ã³ã¡ã³ãã¯ãã®é¢æ°ã«å¿ èŠã§ãããã?
-
é²è¡: PM ããããŒãžã£ãŒãªã©ãåè¬è ãšäœè ã®éã«ç«ã€ä»²ä»åœ¹ã æŒããªããããã®é¢æ°ã®äœè ã¯ãã®ã³ã¡ã³ãã«é£è²ã瀺ããŠãããš åè¬è ã«äŒããŸãã
-
åè¬è ã«å°ãã: ãã®çš®ã®ã³ã¡ã³ãã®äœè ãé£è²ã瀺ãã®ã¯ãªãã§ãããã?
åè¬è ãããªãäœè ãé£è²ã瀺ãã®ããå°ããŠãããŸã 詳现ã¯äŒããªãã§ãã ããã
-
åè¬è ã«å°ãã: åŒã³åºãåŽã¯ã䜿ãããŠãããœãŒãã¢ã«ãŽãªãºã ã ãªãç¥ãå¿ èŠãããã®ã§ãããã?
-
é²è¡: å ã®äœè ãšã®äŒè°ãããæ»ã£ãŠãããããšã«ããŠããã®é¢æ°ã¯ ä¿¡é Œã§ããªãããŒã¿ã«å¯ŸããŠåŒã³åºãããã¢ããªã±ãŒã·ã§ã³ã³ãŒãã§ããã ãã®ããŒã¿ã¯ ãœãŒãäžã«äºæ¬¡æéã®æåãåŒãèµ·ããããæªæãæã£ãŠçް工ãããå¯èœæ§ããã ãšåè¬è ã«èª¬æããŸãã
-
åè¬è ã«å°ãã: ãããŸã§è©³çްãããã£ãä»ããã®é¢æ°ã«ã¯ã©ã®ããã« ã³ã¡ã³ããã¹ãã§ãããã?
ã€ãŸããããããšãå®è£ ã®è©³çްãã©ããã¯ããã®å ¬éãããå¥çŽãäœã ïŒããšãã°ãä¿¡é Œã§ããªãããŒã¿ãæž¡ãããã©ããïŒã«å€§ããäŸåãã æ éãªå€æãå¿ èŠã§ãã
ã³ã¡ã³ãã for ã«ãŒãã䜿ã£ãŠããããšã説æããŠããå ŽåïŒäžèŠãª 詳现ïŒãšãå éšã§äœ¿ãããã¢ã«ãŽãªãºã ã«æ¢ç¥ã®æªçšææ³ãååšããããšã 説æããŠããå ŽåïŒããã¥ã¡ã³ããæ³šæãåããå ã誀ã£ãŠããïŒã®éãã èããŠãã ããã
äºæž¬å¯èœãª API
åœåèŠåã«åŸããäžè¬çãªãã¬ã€ããå®è£ ããããšã§ãAPI ãäºæž¬å¯èœã«ä¿ã¡ãŸãããã
// Copyright 2025 Google LLC // SPDX-License-Identifier: Apache-2.0 /* ããã¯ã©ã®ãã¬ã€ããå®è£ ãã¹ãã§ããããïŒ */ pub struct ApiToken(String); impl ApiToken { // ãã®ã¡ãœããã¯äœãšåŒã¶ã¹ãã§ããããïŒ pub unsafe fn ____(String) -> ApiToken; }
-
äºæž¬å¯èœãª API ãšã¯ãååãåãã·ã°ããã£ãšãã£ã衚é¢çãªè©³çްã«åºã¥ããŠããŠãŒã¶ãŒã API ã®äžéšã«ã€ããŠæšæž¬ã§ãã API ã®ããšã§ãã
-
ããã§ã¯ãRust ã«ãããäžè¬çãªåœåèŠåãèŠãŠãããŸããããã«ããããŠãŒã¶ãŒã¯èªåã®ããŒãºã«åãã¡ãœããããã°ããæ¢ããæ¢åã®ã³ãŒãããã°ããçè§£ã§ããããã«ãªããŸãã
-
ãŸããåãå®è£ ããäžè¬çãªãã¬ã€ããšãèªåã§å®çŸ©ããåã«å¯ŸããŠãããããã€å®è£ ãã¹ãããèŠãŠãããŸãã
åœåèŠå
æ£åŒã§äžè²«ããŠé©çšãããåœåèŠåãããããšã§ãéçºè ã¯ååã ãã¡ã€ã³åºæèšèªã®ããã«æ±ããã¡ãœããã®æ©èœããŠãŒã¹ã±ãŒã¹ã ãã°ããçè§£ã§ããŸãã
Rust ã³ãã¥ããã£ã¯æ©ã段éã§åœåèŠåãçºå±ãããããã æšæºã©ã€ãã©ãªã®ãããªå Žæã§ããã®å€ãã¯äžè²«ããŠããŸãã
- ããã§ã¯ Rust ã®ã¡ãœããåãæ§æããäžè¬çãªèŠçŽ ãåŠã³ã æšæºã©ã€ãã©ãªããã®äŸãšãããã«äŒŽãããã€ãã®æèã瀺ããŸãã
new: ã³ã³ã¹ãã©ã¯ã¿é¢æ°
Rust ã«ã¯ new ããŒã¯ãŒãã¯ãããŸããã代ããã«ãnew ã¯äžè¬çãªæ¥é èŸãŸãã¯ã¡ãœããåãã®ãã®ãšããŠäœ¿ãããŸãã
// èäœæš© 2025 Google LLC // SPDX-License-Identifier: Apache-2.0 impl<T> Vec<T> { fn new() -> Vec<T>; } impl<T> Box<T> { fn new(T) -> Box<T>; }
-
Rust ã«ã¯æ°ããå€ãåæåããããã®
newããŒã¯ãŒãã¯ãªããåŒã³åºã颿°ããçŽæ¥å€ãèšå®ããå€ãããããŸãããnewã¯ãåã«å¯Ÿãããããã©ã«ããã®ã³ã³ã¹ãã©ã¯ã¿é¢æ°ãšããŠæ £ç¿çã«äœ¿ãããŸããããã¯æ§æäžã®ç¹å¥ãªæå³ãæã¡ãŸãããããã¯æ¥é èŸã§ããå ŽåããããåŒæ°ãåãå ŽåããããŸãã
is_[condition]: ããŒã«å€ãã§ãã¯
ããŒã¿åã«é¢ããæ¡ä»¶ããã§ãã¯ããŸãã
// Copyright 2025 Google LLC // SPDX-License-Identifier: Apache-2.0 impl<T> Vec<T> { fn is_empty(&self) -> bool; } impl f32 { fn is_nan(self) -> bool; } impl u32 { fn is_power_of_two(self) -> bool; }
-
å€ã«å¯ŸããããŒã«æ¡ä»¶ã
-
ååã«
notãå«ãã¡ãœããããããisæ¥é èŸãæšå¥šãããŸããæšæºã©ã€ãã©ãªã®ã¡ãœããã«is_not_㮠䜿çšäŸã¯ãããŸãããåã«!value.is_[condition]ã 䜿ã£ãŠãã ããã
[method]_mut: å¯å€åç
§ã¢ã¯ã»ã¹
ã¢ã¯ã»ã¹ç³»ã¡ãœããçšã®ãµãã£ãã¯ã¹ã
// Copyright 2025 Google LLC // SPDX-License-Identifier: Apache-2.0 impl<T> Vec<T> { fn get(&self, index: usize) -> Option<&T>; fn get_mut(&mut self, index: usize) -> Option<&mut T>; } impl<T> [T] { fn iter(&self) -> impl Iterator<Item = &T>; fn iter_mut(&mut self) -> impl Iterator<Item = &mut T>; }
-
ã¡ãœãããå¯å€åç §ãžã®ã¢ã¯ã»ã¹ãæäŸããããšã瀺ããµãã£ãã¯ã¹ã
-
ãã®ã¡ãœãããåŒã³åºã察象ã®å€ã«å¯Ÿããå¯å€ã¢ã¯ã»ã¹ãå¿ èŠã§ãã
-
Rust ã§ã¯å¯å€æ§ãæœè±¡åã§ããªããããå¯å€ã«ãäžå€ã«ã䜿ããã¡ãœããã æžãæ¹æ³ã¯ãããŸããã代ããã«ã颿°ã察ã§å®çŸ©ããŸããäžå€çã«ã¯ ããçãååãä»ããå¯å€çã«ã¯
_mutãµãã£ãã¯ã¹ãä»ããŸãã
ã³ã³ã¹ãã©ã¯ã¿ãŒãšããŠã® with
ã³ã³ã¹ãã©ã¯ã¿ãŒãšããŠã® with ã¯ãåã®æ§æèŠçŽ ã®ãã¡ 1 ã€ã®å€ãèšå®ãã æ®ãã«ã¯ããã©ã«ãå€ã䜿çšããŸãã
with ã¯ãç¹å®ã®èšå®ãæã€ <Type>ãã®ãããªæå³ã§ãã
// Copyright 2025 Google LLC // SPDX-License-Identifier: Apache-2.0 impl<T> Vec<T> { // å°ãªããšã N èŠçŽ åã®ã¡ã¢ãªãåæåããŸããlen ã¯ãŸã 0 ã®ãŸãŸã§ãã fn with_capacity(capacity: usize) -> Vec<T>; }
-
withã¯ã³ã³ã¹ãã©ã¯ã¿ãŒã®æ¥é èŸãšããŠäœ¿ãããããšããããæãäžè¬ç ãªã®ã¯ãã³ã³ãããŒååãã®ããŒãã¡ã¢ãªãåæåãããšãã§ãããã®å Žåã
newã³ã³ã¹ãã©ã¯ã¿ãŒãšã¯ç°ãªããŸããããã¯ãéåžž API å©çšè ãæ°ã«ããªããã®ã®å€ãæå®ããããã§ãã -
ã¯ã©ã¹ãžã®åã: ãªã
from_capacityã§ã¯ãªãã®ã§ããããïŒçã: ã¡ãœããåŒã³åºããšããŠã®
Vec::with_capacityã¯ããcapacity ãæã€ Vec ãäœãããšããŠèªç¶ã«èªããŸããVec::new_capacityãVec::from_capacityãæžãããšãã«ã©ãèªããããèãããšãäœãèµ·ã㊠ããã®ããããŸãäŒããããŸããã
ã³ããŒããŠèšå®ãã with
å€ãã³ããŒãã€ã€ãç¹å®ã®æ¹æ³ã§å€æŽãè¡ãå Žåã« with ã䜿ãããŸãã
with ã¯ã<value> ã®ãããªãã®ã ããäœããç°ãªãããšããæå³ã§ãã
// Copyright 2025 Google LLC // SPDX-License-Identifier: Apache-2.0 impl Path { // åçŽåããäŸã§ãã "/home/me/mortgage.pdf".with_extension("mov") => // "/home/me/mortgage.mov" fn with_extension(&self, ext: &OsStr) -> PathBuf; }
-
å€ãã³ããŒãããã®åŸã§ãã®å€ã®ç¹å®ã®éšåã倿Žããã¡ãœããã«ã¯
withã䜿ããŸããããã§ã®äŸã§ã¯ã
with_extensionã¯&Pathã®ããŒã¿ãæ°ããPathBufã«ã³ããŒããŸãããæ¡åŒµåã¯å¥ã®ãã®ã«å€æŽããŸããå ã®
Pathã¯å€æŽãããŸããã
with: ã¯ããŒãžã£ãæ±ã
with ã¯ããX ãè¡ãããèšç®ã«ã¯ãã®ç¹å®ã®æ¹æ³ã䜿ãããšããæå³ã§ãã
// èäœæš© 2025 Google LLC // SPDX-License-Identifier: Apache-2.0 impl<T> Vec<T> { // ç°¡ç¥åããäŸã§ãããªãµã€ãºåŸã®é·ããçŸåšã® vec ã®ãµã€ãºãã倧ããå Žåã¯ã // ã¯ããŒãžã£ã䜿ã£ãŠèŠçŽ ãåããŸãã pub fn resize_with(&mut self, new_len: usize, f: impl FnMut() -> T); } mod iter { // ã¯ããŒãžã£ã䜿ã£ãŠãç¡éã®é å»¶ã€ãã¬ãŒã¿ãäœæããŸãã pub fn repeat_with<A, F: FnMut() -> A>(repeater: F) -> RepeatWith<F>; }
-
withã¯ãèšç®ã«ãããŠã劥åœãªããã©ã«ããã®ä»£ããã«äœ¿çšã§ããç¹å®ã®é¢æ°ãŸã㯠ã¯ããŒãžã£ãããããšãäŒããããã«ãæ¥å°ŸèŸãšããŠäœ¿ãããããšããããŸããbyãšäŒŒãŠããŸãã
try_[method]: ç¹å®ã®ãšã©ãŒãè¿ã倱æãããã¡ãœãã
Result ãè¿ã倱æãããã¡ãœããã®ãã¬ãã£ãã¯ã¹ã
// èäœæš© 2025 Google LLC // SPDX-License-Identifier: Apache-2.0 impl TryFrom<i32> for u32 { type Error = TryFromIntError; fn try_from(value: i32) -> Result<i64, TryFromIntError>; } impl<T> Receiver<T> { fn try_recv(&self) -> Result<T, TryRecvError>; }
-
倱æããå¯èœæ§ãããã
Resultãè¿ãã¡ãœããã«ä»ãããã¬ãã£ãã¯ã¹ã -
TryFromã¯ãåäžã®å€ãåãåãã³ã³ã¹ãã©ã¯ã¿ãäœããã®åœ¢ã§å€±æãããåã®ããã®ãFromã«äŒŒããã¬ã€ãã§ãã -
çå: ãªã
Vec::getããã®ä»ã®é¡äŒŒã¡ãœããã¯try_getãšåŒã°ããªãã®ã§ããããïŒæ¢åã®å€ãžã®åç §ãè¿ãã倱æã¢ãŒãã 1 ã€ãããªããã
Resultã§ã¯ãªãOptionãè¿ã ã¡ãœããã¯ãgetãšããååã«ãªããŸããããšãã°ãVec::getã§ã¯ãã€ã³ããã¯ã¹ãç¯å²å€ããHashMap::getã§ã¯ãããŒãååšããªããã ãã§ãã
from
ãå倿ãã匷ã瀺åããã³ã³ã¹ãã©ã¯ã¿é¢æ°ã
// Copyright 2025 Google LLC // SPDX-License-Identifier: Apache-2.0 impl Duration { fn from_days(days: u64) -> Duration; } impl i32 { fn from_ascii(src: &[u8]) -> Result<i32, ParseIntError>; } impl u32 { fn from_le_bytes(bytes: [u8; 4]) -> u32; }
-
ã³ã³ã¹ãã©ã¯ã¿ã¹ã¿ã€ã«ã®ã
Fromãã¬ã€ãã¹ã¿ã€ã«ã®é¢æ°ã«å¯Ÿããæ¥é èŸã -
ãããã®é¢æ°ã¯è€æ°ã®åŒæ°ãåãããšãã§ããŸãããéåžžã¯äžè¬çãªã³ã³ã¹ãã©ã¯ã¿ãããããŠãŒã¶ãŒèªèº«ãããå€ãã®äœæ¥ãè¡ãããšã瀺åããŸãã
-
ã»ãšãã©ã®ã³ã³ã¹ãã©ã¯ã¿ã¹ã¿ã€ã«ã®é¢æ°ã§ã¯ãäŸç¶ãšããŠ
newãæšå¥šãããŸããfromã瀺åããã®ã¯ãããããŒã¿åããå¥ã®ããŒã¿åãžã®å€æã§ãã
into
self ãå¥ã®åã«å€æããã¡ãœããã®ããã®ãã¬ãã£ãã¯ã¹ã§ããself ã æ¶è²»ããæææš©ãæã€å€ãè¿ããŸãã
// Copyright 2025 Google LLC // SPDX-License-Identifier: Apache-2.0 pub trait IntoIterator { fn into_iter(self) -> Self::IntoIter; } impl str { fn into_string(self: Box<str>) -> String; }
-
æææš©ãæã€å€ãæ¶è²»ãããããå¥ã®åã®å€ã«å€æãã颿°ã®ããã® ãã¬ãã£ãã¯ã¹ã§ãã
-
reinterpret cast ã§ã¯ãããŸãããããŒã¿ã¯äžŠã¹æ¿ããåé 眮ãä»»æã®åœ¢ã§ã® 倿Žãå¯èœã§ãæ å ±ã倱ãããããšãå«ã¿ãŸãã
-
into_iterã¯ã³ã¬ã¯ã·ã§ã³ïŒvecãbtreesetãhashmap ãªã©ïŒãæ¶è²»ãã æææš©ãæã€å€ã«å¯Ÿããã€ãã¬ãŒã¿ãçæããŸããããã¯ãåç §ã®å€ã«å¯Ÿãã ã€ãã¬ãŒã¿ãçæããiterãiter_mutãšã¯ç°ãªããŸãã
to: å€ãæ¶è²»ããªã倿
åçšãããå€ãåãåããææå€ãäœæãã颿°ã«ä»ããæ¥é èŸ
// Copyright 2025 Google LLC // SPDX-License-Identifier: Apache-2.0 impl str { fn to_owned(&self) -> String; fn to_uppercase(&self) -> String; } impl u32 { // `u32` 㯠`Copy` ãå®è£ ããŠããããã`self` ãå€ã§åãåã fn to_be(self) -> u32; }
-
selfãæ¶è²»ããã«æ°ããææå€ãäœæããå倿ãæå³ããã¡ãœããã¯ãtoã§å§ãŸãååã«ããŸãã -
toã§å§ãŸãã¡ãœããã¯å¥ã®åãè¿ããéèªæãªå倿ããããã¯ããŒã¿å€æã§ããããšã匷ã瀺åããŸããããšãã°ãstr::to_uppercaseã§ãã -
toã¡ãœããã¯éåžž&selfãåãåããŸãããã ãããã®åãCopyãå®è£ ããŠããå Žåã¯ãå€ãšããŠselfãåãåãããšãã§ããŸããããã«ãã£ãŠããã®å€æã¡ãœããåŒã³åºãã§selfãæ¶è²»ãããªãããšãä¿èšŒãããŸãã -
åã«
&selfãåãåããåãåã®ææå€ãè¿ãã¡ãœãããå®çŸ©ãããã ããªããCloneãŸãã¯ToOwnedãå®è£ ããŸãã -
å ã®å€ãæ¶è²»ããã¡ãœãããå®çŸ©ãããå Žåã¯ã
intoãšããåœåãã¿ãŒã³ã䜿ããŸãã -
ãŸããããªããã£ãåã®ãšã³ãã£ã¢ã³ã倿ãã颿°ããnewtype ã®å€ãã³ããŒããŠå ¬éãã颿°ã§ãèŠãããŸãã
ããã«èããŠã¿ãã
-
ã¯ã©ã¹ãžã®è³ªå:
to_ownedãšinto_ownedã®éãã¯äœã§ããããïŒçã:
to_ownedã¯&strã®ãããªåç §å€ã«çŸããäžæ¹ã§ãinto_ownedã¯CowïŒã³ããŒãªã³ã©ã€ãïŒã®ããã«ãåç §åãä¿æããææå€ã«çŸããŸããCowã®ãããªåã¯ãåçšãããŠããåç §ãå«ãã§ããŠããããèªäœã¯ææãããŠããããšããããŸãããã®ãããCowã®ææå€ã¯ããããä¿æããŠããåç §åã®ææå€ãäœæããããã«æ¶è²»ãããŸãã
as_ ãš _ref: åç
§å€æ
// èäœæš© 2025 Google LLC // SPDX-License-Identifier: Apache-2.0 impl<T> Rc<T> { // ã³ã³ããåã§ã¯éåžžã«ããèŠãããŸããOption ã«ãããããšã«æ³šç®ããŠãã ããã fn as_ref(&self) -> &T; fn as_ptr(&self) -> *const T; } impl<T> Option<T> { fn as_ref(&self) -> Option<&T>; fn as_slice(&self) -> &[T]; }
-
å«ãŸããŠããããŒã¿ã®äž»èŠéšåãžã®åçšãè¿ãã¡ãœããã
-
åçšé¢ä¿ã¯ãããŠãåçŽã§ããæ»ãå€ã¯
selfãåçšããåç §ã§ãã -
è¿ãããå€ã
selfãåçšããã®ã¯ãè«ççãªæå³ã«éãããå ŽåããããŸããããšãã°ãas_ptr()ã¡ãœãã㯠unsafe ãªãã€ã³ã¿ãè¿ããŸããåçšãã§ãã«ãŒã¯ãã€ã³ã¿ã«å¯Ÿããåçšã远跡ããŸããã -
asã¡ãœãããå®è£ ããåã¯ãåçšããŠåãåºããã 1 ã€ã®äž»èŠãªããŒã¿ãå«ãã§ããã¹ãã§ãã-
ããŒã¿åããæç¢ºãªäž»èŠéšåãæããªã倿°ã®ãã£ãŒã«ãã®éåäœã§ããå Žåã
asãšããåœåèŠåã¯æ©èœããŸããã -
åºå¥ããå¿ èŠããã 2 ã€ã®åç §ã²ãã¿ãŒãããå Žåã¯ã
_refæ¥å°ŸèŸã䜿ããŸãã
-
by: ã«ã¹ã¿ã æ¯èŒé¢æ°ãŸãã¯å°åœ±
ã«ã¹ã¿ã ã®å°åœ±é¢æ°ãŸãã¯æ¯èŒé¢æ°ãåãåãã¡ãœããã«äœ¿ãæ§æèŠçŽ ã
// èäœæš© 2025 Google LLC // SPDX-License-Identifier: Apache-2.0 impl<T> [T] { fn sort(&mut self) where T: Ord; fn sort_by(&mut self, compare: impl FnMut(&T, &T) -> Ordering); fn sort_by_key<K, F>(&mut self, f: F) where F: FnMut(&T) -> K, K: Ord; }
-
sort_byã¯ãéåžžã®Ordæ¯èŒããžãã¯ã眮ãæããã«ã¹ã¿ã æ¯èŒé¢æ°ãåãåããŸãã -
sort_by_keyã¯ãå ã®èŠçŽ ãåãåãããœãŒãã«äœ¿çšãã代æ¿å€ãè¿ãå°åœ±é¢æ°ãåãåããŸããããã«ãããæ§é äœã®ç¹å®ã®ãã£ãŒã«ãã§ãœãŒããããšãã£ãããšãã§ããŸãã -
ãšãã«ã¯ãåçœ®è© âbyâ ãåã«å眮è©ã§ããã ãã®å ŽåããããŸãã
-
Iterator::advance_by()ã€ãã¬ãŒã¿ã¡ãœããïŒnightly æ©èœïŒ
æŒç¿
- ãããã®ååã¯ãäœããããšç€ºåããŠããŸããïŒ
- ãããã®ã·ã°ããã£ã«ã¯ã©ã®ãããªååãä»ããã¹ãã§ããïŒ
// Copyright 2025 Google LLC // SPDX-License-Identifier: Apache-2.0 // ãããã®ã¡ãœããã®åã¯äœã§ããïŒ Option::is_some // ? slice::get // ? slice::get_unchecked_mut // ? Option::as_ref // ? str::from_utf8_unchecked_mut // ? Rc::get_mut // ? Vec::dedup_by_key // ? // ãããã®åãæã€ã¡ãœããã«ã¯ã©ã®ãããªååãä»ããã¹ãã§ããïŒ fn ____(String) -> Self; fn ____(&self) -> Option<&InnerType>; // InnerType ã®è©³çްã¯éèŠã§ã¯ãããŸããã fn ____(self, String) -> Self; fn ____(&mut self) -> Option<&mut InnerType>;
-
äŸã®ã¡ãœãããé ã«èŠãŠããããã®é¢æ°ã®åãã©ãããã¹ããã è°è«ããŠãã ããã
-
ååã®ãªãã¡ãœãããé ã«èŠãŠããããã®ã¡ãœããã«ã©ã®ãããªååã ä»ããã¹ãããèããŠãã ããã
äžè¶³ããŠããåã®çã:
-
Option::is_some(&self) -> bool -
slice::get(&self /* &[T] */, usize) -> Option<&T> -
slice::get_unchecked_mut(&self /* &[T] */, usize) -> &TïŒunsafe ã〠簡ç¥åãããã®ïŒ -
Option::as_ref(&self /* &Option<T> */) -> Option<&T> -
str::from_utf8_unchecked_mut(v: &mut [u8]) -> &mut strïŒunsafeïŒ -
Rc::get_mut(&mut self /* &mut Rc<T> */) -> Option<&mut T>ïŒç°¡ç¥åãããã®ïŒ -
Vec::dedup_by_key<K: PartialEq>(&mut self /* &mut Vec<T> */, key: impl FnMut(&mut T) -> K)ïŒç°¡ç¥åãããã®ïŒ äžè¶³ããŠããååã®çã: -
fn from_string(String) -> Self -
fn inner(&self) -> Option<&InnerType>ãŸãã¯as_refïŒæèã«ããïŒ -
fn with_string(self, String) -> Self -
fn inner_mut(&mut self) -> Option<&mut InnerType>ãŸãã¯as_ref_mutïŒæèã«ããïŒ
-
å®è£ ãã¹ãäžè¬çãªãã¬ã€ã
// Copyright 2025 Google LLC // SPDX-License-Identifier: Apache-2.0 #[derive(Debug, PartialEq, Eq, PartialOrd, Ord, Hash, Clone /* ... */)] pub struct MyData { pub name: String, pub number: usize, pub data: [u8; 64], }
-
ãã¬ã€ãã¯ãRust èšèªã«ãããæã匷åãªããŒã«ã® 1 ã€ã§ããèšèªãšãšã³ã·ã¹ãã ã¯ãããã䜿ãããšãåæãšããŠãããããäºæž¬å¯èœæ§ ã®å€§ããªéšåã¯ãããåã«ã©ã®ãã¬ã€ããå®è£ ãããŠãããã«ãããŸãã
-
èªåã§äœæããåã«ã¯ãã¬ã€ããç©æ¥µçã«å®è£ ãã¹ãã§ãããæ³šæç¹ããããŸãïŒ
-
å€ãã®ãã¬ã€ã㯠derive ã§ãããã€ãŸãã³ã³ãã€ã©ãã©ã°ã€ã³ïŒãã¯ãïŒã«å®è£ ãæžãããããšãã§ããããšããç¹ãèŠããŠãããŸãããïŒ
-
ãšã³ã·ã¹ãã ã®ãã¬ã€ãïŒDe/Serialize ãªã©ïŒã®äœè ã¯ããŠãŒã¶ãŒãå©çšã§ãã derive å®è£ ãæäŸããŠããããããã®çš®ã®ãã¬ã€ããå®è£ ããéã«éçºè åŽã§å¿ èŠãªè² æ ã¯ãããããã§ãïŒ
Debug
ãããã°çšéã®ãæååãžã®æžã蟌ã¿ããã¬ã€ãã
å°åºå¯èœ: â
// Copyright 2025 Google LLC // SPDX-License-Identifier: Apache-2.0 #[derive(Debug)] pub struct Date { day: u8, month: u8, year: i64, } #[derive(Debug)] pub struct User { name: String, date_of_birth: Date, } pub struct PlainTextPassword { password: String, hint: String, } impl std::fmt::Debug for PlainTextPassword { fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { f.debug_struct("PlainTextPassword") .field("hint", &self.hint) .field("password", &"[omitted]") .finish() } } fn main() { let user = User { name: "Alice".to_string(), date_of_birth: Date { day: 31, month: 10, year: 2002 }, }; println!("{user:?}"); println!( "{:?}", PlainTextPassword { password: "Password123".to_string(), hint: "Used it for years".to_string() } ); }
-
åçŽãªãæååãžã®æžã蟌ã¿ãæ©èœãæäŸããŸãã
-
éçºäžã«ããã°ã©ããŒåãã®_ãããã°æ å ±_ãæŽåœ¢ããããã®ãã®ã§ããã èŠãç®ãã·ãªã¢ã©ã€ãºã®ããã®ãã®ã§ã¯ãããŸããã
-
æååãã©ãŒããããã¯ãã§
{:?}ãš{#?}ã®è£éã䜿çšã§ããŸãã -
derive/å®è£ ãè¡ãã¹ãã§ãªãã±ãŒã¹: æ§é äœãæ©åŸ®ãªããŒã¿ãä¿æããŠããå Žåã¯ã ãã®åã«
Debugãå®è£ ãã¹ããæ€èšããŠãã ãããDebugãå¿ èŠãªå Žåã¯ãderive ããã®ã§ã¯ãªãDebugãæåã§å®è£ ããããšã æ€èšããŠãã ãããå®è£ ããæ©åŸ®ãªããŒã¿ãé€å€ããŠãã ããã
Display
ãšã³ããŠãŒã¶ãŒã«ãšã£ãŠã®èªã¿ããããåªå ããããæååãžæžã蟌ãããã¬ã€ãã
derive å¯èœ: âïŒderive_more ã®ãããªã¯ã¬ãŒãã䜿ããªãå ŽåïŒ
// Copyright 2025 Google LLC // SPDX-License-Identifier: Apache-2.0 #[derive(Debug)] pub enum NetworkError { HttpCode(u16), WhaleBitTheUnderseaCable, } impl std::fmt::Display for NetworkError { fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { match self { NetworkError::HttpCode(code) => write!(f, "HTTP Error code {code}"), NetworkError::WhaleBitTheUnderseaCable => { write!(f, "Whale attack detected â call Ishmael") } } } } fn main() { let http = NetworkError::HttpCode(404); let whale = NetworkError::WhaleBitTheUnderseaCable; println!("http debug: {:?}", http); println!("http display: {}", http); println!("whale debug: {:?}", whale); println!("whale display: {}", whale); }
-
Debugã«äŒŒããã¬ã€ãã§ããããšã³ããŠãŒã¶ãŒã«ãšã£ãŠã®èªã¿ãããã«éç¹ããããŸãã -
Errorãã¬ã€ãã®åææ¡ä»¶ã§ãããšã©ãŒåã«å®è£ ããå Žåã¯ãèªå以å€ã®ãŠãŒã¶ãŒãããã°ã©ããŒã« ãšã£ãŠèª¬æçãªãšã©ãŒãæäŸããããšã«éç¹ã眮ããŠãã ããã -
Debug ãšåãã»ãã¥ãªãã£äžã®èæ ®äºé ããããŸããæ©å¯ããŒã¿ã UI ããã°ã§ ã©ã®ããã«é²åºãããããæ€èšããŠãã ããã
-
Displayãå®è£ ããåã«ã¯ãèªåçã«ToStringãå®è£ ãããŸãã -
äŸã®ãšã©ãŒåã«ã€ããŠã
DebugãšDisplayã®æ¯ãèããæ¯èŒããŠãã ãããDebugã® impl ã¯ã³ãŒãäžã§çŸããããŒã¿ãããçŽæ¥çã«è¡šãäžæ¹ãDisplay㯠éããã°ã©ããŒã«ãã芪ãã¿ãããã¡ãã»ãŒãžãæäŸããããšã瀺ããŠãã ããã
PartialEq ãš Eq
éšåçç䟡æ§ãšå®å šãªç䟡æ§ã
å°åºå¯èœ: â
// Copyright 2025 Google LLC // SPDX-License-Identifier: Apache-2.0 #[derive(PartialEq, Eq)] pub struct User { name: String, favorite_number: i32 } fn main() { let alice = User { name: "alice".to_string(), favorite_number: 1_000_042 }; let bob = User { name: "bob".to_string(), favorite_number: 42 }; dbg!(alice == alice); dbg!(alice == bob); }
-
ç䟡æ§ã«é¢ããã¡ãœãããåã
PartialEqãå®è£ ããŠããå Žåããã®åã§==/!=æŒç®åã䜿çšã§ããŸãã -
åã¯
PartialEqãå®è£ ããã«Eqãå®è£ ããããšã¯ã§ããŸããã -
è£è¶³: Partial ã¯ããã®é¢æ°ã«å¯ŸããŠããã®éåã«ã¯åŠ¥åœã§ãªãèŠçŽ ãååšããã ããšãæå³ããŸãã
ããã¯ãç䟡æ§ã®å€å®ã panic ããããšããäœããã®çµæãè¿ãããšãæå³ãã ã®ã§ã¯ãªããåã«ãç䟡æ§ãæåŸ ã©ããã«æ¯ãèããªãå€ãååšããããšããããš ã§ãã
ããšãã°æµ®åå°æ°ç¹å€ã§ã¯ã
NaNã¯äŸå€çãªååšã§ãããããåäœã§ã¯çããã«ã ããããããNaN == NaN㯠false ã§ããPartialEqã¯ãf32/f64ã®ãããªåããå®å šãªç䟡æ§ãæã€åãšåºå¥ãã ããã«ååšããŸãã -
ç°ãªãåã®éã§
PartialEqãå®è£ ããããšãã§ããŸãããããã¯äž»ã« åç §/ã¹ããŒããã€ã³ã¿åã§æçšã§ãã
PartialOrd ãš Ord
åé åºãšå šé åºã
å°åºå¯èœ: â
// Copyright 2025 Google LLC // SPDX-License-Identifier: Apache-2.0 #[derive(PartialEq, PartialOrd)] pub struct Partially(f32); #[derive(PartialEq, Eq, PartialOrd, Ord)] pub struct Totally { id: u32, name: String, } fn main() { let a = Totally { id: 0, name: "alice".into() }; let b = Totally { id: 1, name: "alice".into() }; let c = Totally { id: 0, name: "charlie".into() }; dbg!(a.cmp(&b)); dbg!(a.cmp(&c)); }
-
æ¯èŒã«é¢é£ããã¡ãœããã§ããåã
PartialOrd/Ordãå®è£ ããŠããã°ããã®åã«å¯ŸããŠæ¯èŒæŒç®åïŒ<,<=,>,>=ïŒã䜿çšã§ããŸãã -
Ordã«ãããminãmaxãclampã¡ãœããã䜿çšã§ããŸãã -
derive ããå Žåã¯ãå®çŸ©ãããé åºã§æ¯èŒãããŸãã
enum ã§ã¯ãããã¯åããªã¢ã³ãããèšè¿°ãããé ã«åã®ãã®ããã倧ããããšèŠãªãããããšãæå³ããŸãã
struct ã§ã¯ãããã¯ãã£ãŒã«ããèšè¿°ãããé ã«æ¯èŒãããããšãæå³ããããã
Totallyã§ã¯nameãã£ãŒã«ãããåã«idãã£ãŒã«ããæ¯èŒãããŸãã -
åææ¡ä»¶:
PartialOrdã«ã¯PartialEqãOrdã«ã¯Eqãå¿ èŠã§ããOrdãå®è£ ããã«ã¯ãåã¯PartialEqãEqãPartialOrdãå®è£ ããŠããªããã°ãªããŸããã -
PartialEqãšEqã®å Žåãšåæ§ã«ãåã¯PartialOrdãå®è£ ããã«Ordãå®è£ ããããšã¯ã§ããŸããããããã®ç䟡æ§ãã¬ã€ããšåæ§ã«ã
PartialOrdã¯ãå šé åºã§ã¯ãªãé åºä»ããæã€åïŒç¹ã«æµ®åå°æ°ç¹æ°ïŒãšå šé åºãæã€åãåããããã«ååšããŸãã -
ãœãŒã/æ€çŽ¢ã¢ã«ãŽãªãºã ãã
BTreeMap/BTreeSetã¹ã¿ã€ã«ã®ããŒã¿åã®é åºãç¶æããããã«äœ¿çšãããŸãã
Hash
åã«å¯ŸããŠããã·ã¥åãè¡ããŸãã
derive å¯èœ: â
// Copyright 2025 Google LLC // SPDX-License-Identifier: Apache-2.0 use std::collections::HashMap; #[derive(PartialEq, Eq, Hash)] pub struct User { id: u32, name: String, } fn main() { let user = User { id: 1, name: "Alice".into() }; let mut map = HashMap::new(); map.insert(user, "value"); }
-
åãããã·ã¥ã¢ã«ãŽãªãºã ã§äœ¿çšã§ããããã«ããŸããæãäžè¬çã«ã¯ã
HashMapã®ãããªããŒã¿æ§é ã§äœ¿ãããŸãã -
HashMapã®ããŒãšããŠã«ã¹ã¿ã åã䜿ãã®ãéåžžã«ç°¡åã«ãªããŸãïŒ -
Hashèªäœã¯ããã·ã¥åããžãã¯ãäœãå®çŸ©ããã代ããã«åã®ããŒã¿ãHasherã«æž¡ãã ãã§ããããã«ãããåã®Hashimpl ã倿Žããããšãªããç°ãªãããã·ã¥ã¢ã«ãŽãªãºã ã䜿çšã§ããŸãã
Clone
åããã£ãŒãã³ããŒããããå ±æå¯èœãªã¹ããŒããã€ã³ã¿ãè€è£œããŸãã
derive å¯èœ: â
// èäœæš© 2025 Google LLC // SPDX-License-Identifier: Apache-2.0 use std::collections::BTreeSet; use std::rc::Rc; #[derive(Clone)] pub struct LotsOfData { string: String, vec: Vec<u8>, set: BTreeSet<u8>, } fn main() { let lots_of_data = LotsOfData { string: "String".to_string(), vec: vec![1; 255], set: BTreeSet::from_iter([1, 2, 3, 4, 5, 6, 7, 8]), }; // `lots_of_data` å ã®ãã¹ãŠã®ããŒã¿ããã£ãŒãã³ããŒããã let lots_of_data_cloned = lots_of_data.clone(); let reference_counted = Rc::new(lots_of_data); // å€ã§ã¯ãªããåç §ã«ãŠã³ãä»ããã€ã³ã¿ãã³ããŒããã let reference_copied = reference_counted.clone(); }
-
å€ãããã£ãŒãã³ããŒããããã
Rc/Arcã®ãããªåç §ã«ãŠã³ãä»ã ãã€ã³ã¿ã®å Žåã¯ããã®ãã€ã³ã¿ã®æ°ããã€ã³ã¹ã¿ã³ã¹ãäœæããŸãã -
å®è£ /derive ããªãã¹ãå Žå: äžå€æ¡ä»¶ãç¶æããããã«ããã® å€ã¯è€è£œãããã¹ãã§ã¯ãªãåã§ããããã«ã€ããŠã¯ãIdiomatic Rust ã®åŸã®æ¹ã§è§ŠããŸãã
Copy
Clone ã«äŒŒãŠããŸãããåããããåäœã§ã³ããŒå¯èœã§ããããšã瀺ããŸãã
derive å¯èœ: â
// Copyright 2025 Google LLC // SPDX-License-Identifier: Apache-2.0 #[derive(Debug, Clone, Copy)] pub struct Copyable(u8, u16, u32, u64); fn main() { let copyable = Copyable(1, 2, 3, 4); let copy = copyable; // æé»çãªã³ããŒæäœ dbg!(copyable); dbg!(copy); }
-
Cloneã¯æç€ºçãªããŠãŒã¶ãŒå®çŸ©ã®ã³ããŒæäœã衚ããŸããCopyã¯æé»çãªãããåäœã³ããŒã衚ããŸãã -
äžè¬ã«ãããªããã£ãå€ã®ããã«æ¯ãèãã¹ãããã¬ãŒã³ããŒã¿ãåã«ã®ã¿å®è£ ãã¹ãã§ããããšãã°ãç·åœ¢ä»£æ°ã©ã€ãã©ãªã«ãããããªããã£ããªæ°å€åãªã©ã§ãã
-
Cloneãšåãæ³šæç¹ããããŸããå€ãè€è£œãããšäžå€æ¡ä»¶ãç Žãããªãããã®åã¯Copyãå®è£ ãã¹ãã§ã¯ãããŸããã -
CloneãšCopyã¯å¿ ãäžç·ã« derive ããŸãããïŒCopyãå®è£ ãããšãã«Cloneãæåã§å®è£ ããŠã¯ãããŸããã- ã³ããŒæäœã§ã¯
cloneã¡ãœããã¯åŒã³åºãããªããããç¬èªã®Cloneå®è£ ã¯æé»çãªã³ããŒæäœãšã¯ç°ãªãæ¯ãèããããå¯èœæ§ããããŸããCloneãšCopyãäž¡æ¹äžç·ã« derive ããããšã§ãcloneãåŒã³åºããçµæãã³ããŒãè¡ã£ãå Žåãšåãã«ãªãããšãä¿èšŒãããŸãã
- ã³ããŒæäœã§ã¯
-
DropãŸãã¯Copyã§ãªããã£ãŒã«ããæã€åã«ã¯å®è£ ã§ããŸããã-
ã¯ã©ã¹ã«è³ªåããŠã¿ãŸããã: ããŒãããŒã¿ïŒ
VecãBTreeMapãRcãªã©ïŒãæã€åã¯ããªãCopyã«ã§ããªãã®ã§ããããïŒãããã®åã«å¯ŸããŠãããåäœã³ããŒãè¡ããšãããŒãããŒã¿ãæã€åããã€ã³ã¿ã®æä»çæææš©ã倱ããRust ãšãã®ãšã³ã·ã¹ãã ãéåžžä¿ã£ãŠããäžå€æ¡ä»¶ãå£ãããšã«ãªããŸãã
è€æ°ã®
Vecãã¡ã¢ãªå ã®åãããŒã¿ãæãããšã«ãªããŸããããŒã¿ã®è¿œå ãåé€ã¯ãããããã®Vecã®é·ããšå®¹éã®å€ããæŽæ°ããŸãããBTreeMapã§ãåæ§ã§ããRcããããåäœã§ã³ããŒããŠãããã€ã³ã¿å ã®åç §ã«ãŠã³ãå€ã¯æŽæ°ãããŸããããã®çµæãèªåããã®ãã€ã³ã¿ã«å¯Ÿããå¯äžã®Rcã ãšæã£ãŠããRcå€ã®ã€ã³ã¹ã¿ã³ã¹ã 2 ã€ååšãããããšã«ãªããŸãããã®ãã¡ 1 ã€ãç Žæ£ããããšããã 1 ã€ã®RcããŸã çããŠããã«ãããããããçæ¹ã§ã¯åç §ã«ãŠã³ãã 0 ã«ãªããå éšã®å€ããããããããŠããŸããŸãã
-
From ãš Into
ããåããå¥ã®åãžã®å€æã
å°åºå¯èœ: âãderive_more ã®ãããªã¯ã¬ãŒããªãã§ã¯äžå¯ã
// Copyright 2025 Google LLC // SPDX-License-Identifier: Apache-2.0 pub struct Wrapper(String); impl From<&str> for Wrapper { fn from(value: &str) -> Self { Wrapper(value.to_owned()) } } impl From<i32> for Wrapper { fn from(value: i32) -> Self { Wrapper(value.to_string()) } } // ãã¬ã€ãå¢çãšããŠäœ¿ãå Žå㯠`Into` ã®ã»ããèªç¶ã§ãã fn into_string<S: Into<String>>(s: S) {} fn string_from<T>(t: T) where String: From<T> {} fn main() { // `Wrapper` 㯠`&str` ãš `i32` ããæ§ç¯ã§ããŸãã let a = Wrapper::from("Hello, obvious!"); let b = Wrapper::from(-123); // From ã®å®è£ ãããã°ãInto ã®å®è£ ã嫿ãããŸãã let c: Wrapper = "Hello, implementation!".into(); }
-
åå€æã®æ©èœãæäŸããŸãã
-
Fromã¯ã³ã³ã¹ãã©ã¯ã¿é¢šã®é¢æ°ãæäŸããäžæ¹Intoã¯æ¢åã®å€ã«å¯Ÿããã¡ãœãã ãæäŸããŸãã -
èªåãäœæããŠããåã«å¯ŸããŠã¯ã
Into<T>ã§ã¯ãªãFrom<T>ã®å®è£ ãæžãããšãæšå¥šããŸããFromãå®è£ ããŠããä»»æã®åã«å¯ŸããŠã¯ãIntoãã¬ã€ããèªåçã« å®è£ ãããŸãã -
颿°ã®åŒæ°ã«å¯Ÿãããã¬ã€ãå¢çãšããŠã¯ã颿°ãåãåãããã®ã®æå³ãæç¢ºã«ããããã
Intoãæšå¥šãããŸããT: Into<String>ã®ã»ããString: From<T>ããæå³ã æç¢ºã§ãã
TryFrom/TryInto
ããåããå¥ã®åãžã®ã倱æããå¯èœæ§ããã倿ã
å°åºå¯èœ: â
// Copyright 2025 Google LLC // SPDX-License-Identifier: Apache-2.0 #[derive(Debug)] pub struct InvalidNumber; #[derive(Debug)] pub struct DivisibleByTwo(usize); impl TryFrom<usize> for DivisibleByTwo { type Error = InvalidNumber; fn try_from(value: usize) -> Result<Self, InvalidNumber> { if value.rem_euclid(2) == 0 { Ok(DivisibleByTwo(value)) } else { Err(InvalidNumber) } } } fn main() { let success: Result<DivisibleByTwo, _> = 4.try_into(); dbg!(success); let fail: Result<DivisibleByTwo, _> = 5.try_into(); dbg!(fail); }
-
倱æããå¯èœæ§ã®ãã倿ãæäŸããçµæåãè¿ããŸãã
-
From/Intoãšåæ§ã«ãTryIntoã§ã¯ãªã åã«å¯ŸããŠTryFromãå®è£ ããããšãæšå¥šããŸãã -
å®è£ ã§ã¯ã
Resultã®ãšã©ãŒåãæå®ã§ããŸãã
Serialize/Deserialize ã¹ã¿ã€ã«ã®ãã¬ã€ã
serde ã®ãããªã¯ã¬ãŒãã§ã¯ãã·ãªã¢ã©ã€ãºãèªåçã«å®è£
ã§ããŸãã
å°åºå¯èœ: â
// èäœæš© 2025 Google LLC // SPDX-License-Identifier: Apache-2.0 #[derive(Serialize, Deserialize)] struct ExtraData { fav_color: String, name_of_dog: String, } #[derive(Serialize, Deserialize)] struct Data { name: String, age: usize, extra_data: ExtraData, }
-
åã«ã·ãªã¢ã©ã€ãºããã³ãã·ãªã¢ã©ã€ãºæ©èœãæäŸããRust ã®ããŒã¿åã JSON ã®ãããªããŒã¿åœ¢åŒã«å€æãããããããã倿ãããã§ããããã«ããŸãã
-
æšæºã©ã€ãã©ãªã«ã¯ã·ãªã¢ã©ã€ãºæ©èœãçµã¿èŸŒãŸããŠããŸãããã serde ã¯ã¬ãŒãã¯ã·ãªã¢ã©ã€ãºãè¡ãããã®ã³ãã¥ããã£æšæºã®ã€ã³ã¿ãŒãã§ãŒã¹ã§ãã
-
å®è£ ãã¹ãã§ãªãå Žå: åã«ã誀ã£ãŠãã£ã¹ã¯ã«ä¿åãããã ãããã¯ãŒã¯è¶ãã«éä¿¡ãããããã¹ãã§ãªãæ©å¯ããŒã¿ãå«ãŸããå Žåã¯ã ãã®åã« Serialize/Deserialize ãå®è£ ããªãããšãæ€èšããŠãã ããã
Debugãšåæ§ã®ã»ãã¥ãªãã£äžã®æžå¿µããããŸãããã·ãªã¢ã©ã€ãºã¯ãã°ãã° ãããã¯ãŒã¯éä¿¡ã§äœ¿ããããããããé倧ãªåé¡ã«ãªãåŸãŸãã
åã·ã¹ãã ãæŽ»çšãã
Rust ã®åã·ã¹ãã 㯠衚çŸåãé«ããåãšãã¬ã€ãã䜿ã£ãŠ ã³ãŒãã誀çšãã«ããããæœè±¡åãæ§ç¯ã§ããŸãã
å Žåã«ãã£ãŠã¯ãå®è¡æãªãŒããŒããããªãã«ãã³ã³ãã€ã«æ ã« æ£ãããä¿èšŒãããšãããŸã§èžã¿èŸŒããŸãã
åãšãã¬ã€ãã¯ãããžãã¹ãã¡ã€ã³ã®æŠå¿µãå¶çŽãã¢ãã«åã§ããŸãã æ³šææ·±ãèšèšããã°ãã³ãŒãããŒã¹å šäœã®æçããšä¿å®æ§ã åäžãããããŸãã
話è ã远å ã§èšåããŠãããé ç®:
-
Rust ã®åã·ã¹ãã ã¯ã颿°åããã°ã©ãã³ã°èšèªããå€ãã®ã¢ã€ãã¢ã åãå ¥ããŠããŸãã
ããšãã°ãRust ã® enum ã¯ãHaskell ã OCaml ã®ãããªèšèªã§ã¯ ã代æ°çããŒã¿åããšããŠç¥ãããŠããŸããåã䜿ã£ãèšèšã®æéã æ¢ãéã«ã¯ã颿°åèšèªåãã®åŠç¿è³æãåèã«ã§ããŸãã âDomain Modeling Made Functionalâ ã¯ãã®ããŒãã«é¢ããåªãã è³æã§ãäŸã¯ F# ã§æžãããŠããŸãã
-
Rust ã«ã¯é¢æ°åã®ã«ãŒãããããŸããããã¹ãŠã®é¢æ°åèšèšãã¿ãŒã³ã ãã®ãŸãŸ Rust ã«ç°¡åã«æã¡èŸŒããããã§ã¯ãããŸããã
ããšãã°ãRust ã§é«é颿°ãé«ã«ã€ã³ãåãæŽ»çšãã API ãèšèšããã«ã¯ã å¹ åºãé«åºŠãªãããã¯ã«ã€ããŠç¢ºããªçè§£ãå¿ èŠã§ãã
ã±ãŒã¹ããšã«ãããåœä»€çãªã¢ãããŒãã®ã»ããå®è£ ãããããã©ããã è©äŸ¡ããŠãã ãããRust ã®åçšãã§ãã«ãŒãšåã·ã¹ãã ãæŽ»çšããŠã äœãã©ãã§å€æŽã§ããããå¶åŸ¡ãã€ã€ãã€ã³ãã¬ãŒã¹ãªå€æŽã䜿ãããšã æ€èšããŠãã ããã
-
åãæ³šæã¯ããªããžã§ã¯ãæåã®èšèšãã¿ãŒã³ã«ãåœãŠã¯ãŸããŸããRust ã¯ç¶æ¿ããµããŒãããŠãããããªããžã§ã¯ãã®åè§£ã¯åçšãã§ãã«ãŒã å°å ¥ããå¶çŽãèæ ®ã«å ¥ããå¿ èŠããããŸãã
-
åã¬ãã«ããã°ã©ãã³ã°ã¯ãã°ãã°ããŒãã³ã¹ãæœè±¡åããå®çŸãããã㫠䜿ãããã®ã®ããã®è¡šçŸã¯èª€è§£ãæãããããããããšã«ãè§ŠããŠãã ããã ã³ã³ãã€ã«æéãã³ãŒãã®è€éããžã®åœ±é¿ã¯å€§ããå ŽåããããŸãã
segment outline
Newtype ãã¿ãŒã³
newtype ã¯æ¢åã®åïŒå€ãã®å Žåã¯ããªããã£ãåïŒãå ãã©ãããŒã§ãã
// èäœæš© 2025 Google LLC // SPDX-License-Identifier: Apache-2.0 /// `u64` ãå ã newtype ãšããŠå®è£ ããããäžæã®ãŠãŒã¶ãŒèå¥åã pub struct UserId(u64);
åãšã€ãªã¢ã¹ãšã¯ç°ãªããnewtype ã¯å ãã§ããåãšçžäºã«çœ®ãæããããšã¯ã§ããŸããã
// èäœæš© 2025 Google LLC // SPDX-License-Identifier: Apache-2.0 pub struct UserId(u64); fn needs_user(user: UserId) { // ... } fn main() { needs_user(1); // ð ïžâ }
ãŸããRust ã³ã³ãã€ã©ã¯ãåºã«ãªãåã«å®çŸ©ãããã¡ãœãããæŒç®åã䜿ãããšãèš±å¯ããŸããã
// èäœæš© 2025 Google LLC // SPDX-License-Identifier: Apache-2.0 pub struct UserId(u64); fn main() { assert_ne!(UserId(1), UserId(2)); // ð ïžâ }
-
åè¬è ã¯ãã¿ãã«æ§é äœ ã«ã€ã㊠åŠãã ãFundamentalsãã³ãŒã¹ã§ãnewtype ãã¿ãŒã³ã«è§ŠããŠããã¯ãã§ãã
-
äŸãå®è¡ããŠãã³ã³ãã€ã©ããã®ãšã©ãŒã¡ãã»ãŒãžãåè¬è ã«ç€ºããŠãã ããã
-
newtype ã®ä»£ããã«åãšã€ãªã¢ã¹ã䜿ãããã«äŸã倿ŽããŠãã ãããããšãã°
type MessageId = u64ã§ããä¿®æ£åŸã®äŸã¯ã³ã³ãã€ã«ã§ããã¯ãã§ãããã«ãã£ãŠ 2 ã€ã®ã¢ãããŒãã®éããæç¢ºã«ãªããŸãã -
newtype ã«ã¯ãäœãããªããã°æ¯ãèããäœãåãã£ãŠããªãããšã匷調ã㊠ãã ãããåºã«ãªãåããã©ã®ã¡ãœãããæŒç®åã転éããŠãããã¯ãæå³ç㫠決ããå¿ èŠããããŸãããã®
UserIdã®äŸã§ã¯ãUserIdåå£«ã®æ¯èŒãèš±å¯ ããã®ã¯åŠ¥åœã§ãããå ç®ãæžç®ã®ãããªç®è¡æŒç®ãèš±å¯ããã®ã¯æå³ããã㟠ããã
æå³äžã®æ··å
颿°ãåãåã®åŒæ°ãè€æ°åãåãå ŽåãåŒã³åºãç®æããã¯æå³ãåããã«ãããªããŸã:
// èäœæš© 2025 Google LLC // SPDX-License-Identifier: Apache-2.0 struct LoginError; fn login(username: &str, password: &str) -> Result<(), LoginError> { // [...] Ok(()) } fn main() { let password = "password"; let username = "username"; // ã³ãŒãããŒã¹ã®å¥ã®ç®æã§ã誀ã£ãŠåŒæ°ãå ¥ãæ¿ããŠããŸããŸãã // ãã°ïŒæåã®å ŽåïŒãã»ãã¥ãªãã£è匱æ§ïŒææªã®å ŽåïŒ login(password, username); }
newtype ãã¿ãŒã³ã䜿ããšããã®çš®ã®ãšã©ãŒãã³ã³ãã€ã«æã«é²ããŸã:
// èäœæš© 2025 Google LLC // SPDX-License-Identifier: Apache-2.0 struct Username(String); struct Password(String); struct LoginError; fn login(username: &Username, password: &Password) -> Result<(), LoginError> { // [...] Ok(()) } fn main() { let password = Password("password".into()); let username = Username("username".into()); login(password, username); // ð ïžâ }
-
äž¡æ¹ã®äŸãå®è¡ããŠãå ã®äŸã¯æ£åžžã«ã³ã³ãã€ã«ããã倿ŽåŸã®äŸã§ã¯ã³ã³ãã€ã©ãšã©ãŒãè¿ãããããšãåè¬è ã«ç€ºããŠãã ããã
-
_æå³äžã®_芳ç¹ã匷調ããŠãã ãããnewtype ãã¿ãŒã³ã¯ãç°ãªãæŠå¿µã«ã¯ç°ãªãåã䜿ãããã«æŽ»çšãã¹ãã§ãããããã«ãã£ãŠãã®çš®ã®ãšã©ãŒãå®å šã«æé€ã§ããŸãã
-
ãã ãã颿°ãåãåã®åŒæ°ãè€æ°åãåãããšãæ£åœãªã·ããªãªãããç¹ã«ã¯æ³šæããŠãã ããããã®ãããªã·ããªãªã§æ£ãããæéèŠã§ãããªããå ¥åãšããŠååä»ããã£ãŒã«ããæã€ struct ã®äœ¿çšãæ€èšããŠãã ãã:
#![allow(unused)] fn main() { // èäœæš© 2025 Google LLC // SPDX-License-Identifier: Apache-2.0 pub struct LoginArguments<'a> { pub username: &'a str, pub password: &'a str, } fn login(i: LoginArguments) {} let password = "password"; let username = "username"; // åé¡ãèŠã€ããããã« `login` 颿°ã®å®çŸ©ã確èªããå¿ èŠã¯ãããŸããã login(LoginArguments { username: password, password: username, }) }ãŠãŒã¶ãŒã¯åŒã³åºãç®æã§åãã£ãŒã«ãã«å€ãå²ãåœãŠãããšã匷å¶ãããããããã°ã«æ°ã¥ããå¯èœæ§ãé«ãŸããŸãã
çææã«äžå€æ¡ä»¶ã匷å¶ãã
newtype ãã¿ãŒã³ã掻çšãããšãäžå€æ¡ä»¶ ã匷å¶ã§ããŸãã
// Copyright 2025 Google LLC // SPDX-License-Identifier: Apache-2.0 pub struct Username(String); impl Username { pub fn new(username: String) -> Result<Self, InvalidUsername> { if username.is_empty() { return Err(InvalidUsername::CannotBeEmpty) } if username.len() > 32 { return Err(InvalidUsername::TooLong { len: username.len() }) } Ok(Self(username)) } pub fn as_str(&self) -> &str { &self.0 } } pub enum InvalidUsername { CannotBeEmpty, TooLong { len: usize }, }
-
newtype ãã¿ãŒã³ã¯ãRust ã®ã¢ãžã¥ãŒã«ã·ã¹ãã ããã³å¯èŠæ§ã·ã¹ãã ãšçµã¿åãããããšã§ã ããåã®ã€ã³ã¹ã¿ã³ã¹ãäžé£ã® äžå€æ¡ä»¶ãæºããããšã ä¿èšŒ ããããã«äœ¿çšã§ããŸãã
äžã®äŸã§ã¯ã
Usernameæ§é äœã®å éšã«æ ŒçŽãããŠããçã®Stringã«ã¯ã ä»ã®ã¢ãžã¥ãŒã«ãã¯ã¬ãŒãããçŽæ¥ã¢ã¯ã»ã¹ã§ããŸãããããã¯ããããpubãpub(in ...)ãšããŠããŒã¯ãããŠããªãããã§ããUsernameåã®å©çšè ã¯ã ã€ã³ã¹ã¿ã³ã¹ãäœæããããã«newã¡ãœããã䜿ãããšã匷å¶ãããŸãããã®çµæãnewãããªããŒã·ã§ã³ãå®è¡ããUsernameã®ãã¹ãŠã®ã€ã³ã¹ã¿ã³ã¹ããããã®ãã§ãã¯ãæºããããšã ä¿èšŒããŸãã -
as_strã¡ãœããã«ãããå©çšè ã¯çã®æåå衚çŸã«ã¢ã¯ã»ã¹ã§ããŸã ïŒããšãã°ããããããŒã¿ããŒã¹ã«ä¿åããããã«ïŒããã ããæ»ãå€ã®åã§ãã&strã¯èªã¿åãå°çšã®ã¢ã¯ã»ã¹ã«å¶éãããããå©çšè ã¯åºã«ãªãå€ã 倿Žã§ããŸããã -
åã¬ãã«ã®äžå€æ¡ä»¶ã«ã¯ã坿¬¡çãªå©ç¹ããããŸãã
å ¥åã¯å¢çã§äžåºŠã ãæ€èšŒããããã®åŸã®ããã°ã©ã ã®æ®ãã®éšå㯠äžå€æ¡ä»¶ãç¶æãããŠããããšãåæã«ã§ããŸããããã«ãããããã°ã©ã å šäœã«ããã åé·ãªæ€èšŒããé²åŸ¡çããã°ã©ãã³ã°ãã®ãã§ãã¯ãé¿ãããããã€ãºãæžãã ããã©ãŒãã³ã¹ãåäžã§ããŸãã
æ¬åœã«ã«ãã»ã«åãããŠãããïŒ
newtype ãå ¬éãã API ãµãŒãã§ã¹å šäœ ãè©äŸ¡ããŠãäžå€æ¡ä»¶ãæ¬åœã«ç€ç³ãã©ããã倿ããªããã°ãªããŸããããŠãŒã¶ãŒãããªããŒã·ã§ã³ãã§ãã¯ãåé¿ã§ããŠããŸãå¯èœæ§ã®ããããã¬ã€ãå®è£ ãå«ãããããçžäºäœçšãèæ ®ããããšãéèŠã§ãã
// Copyright 2025 Google LLC // SPDX-License-Identifier: Apache-2.0 pub struct Username(String); impl Username { pub fn new(username: String) -> Result<Self, InvalidUsername> { // ããªããŒã·ã§ã³ãã§ãã¯... Ok(Self(username)) } } impl std::ops::DerefMut for Username { // âŒïž fn deref_mut(&mut self) -> &mut Self::Target { &mut self.0 } } impl std::ops::Deref for Username { type Target = str; fn deref(&self) -> &Self::Target { &self.0 } } pub struct InvalidUsername;
-
DerefMutã䜿ããšããŠãŒã¶ãŒã¯ã©ãããããå€ãžã®å¯å€åç §ãååŸã§ããŸãããã®å¯å€åç §ã¯ã
Username::newã匷å¶ããäžå€æ¡ä»¶ã«éåããã圢ã§ãåºã«ãªãããŒã¿ã倿Žããããã«äœ¿ããŠããŸããŸãïŒ -
newtype ã® API ãµãŒãã§ã¹ãç£æ»ããéã¯ãã¬ãã¥ãŒç¯å²ããåºã«ãªãããŒã¿ãžã®å¯å€ã¢ã¯ã»ã¹ãæäŸããã¡ãœããããã¬ã€ãã«çµã蟌ããŸãã
-
åŠçã«ãã©ã€ãã·ãŒå¢çãæãåºãããŠãã ããã
ç¹ã«ãnewtype ãšåãã¢ãžã¥ãŒã«å ã§å®çŸ©ããã颿°ãã¡ãœããã¯ããã®åºã«ãªãããŒã¿ã«çŽæ¥ã¢ã¯ã»ã¹ã§ããŸããå¯èœã§ããã°ãç£æ»ã®å¯Ÿè±¡ç¯å²ãçããããã«ãnewtype ã®å®çŸ©ãããå°çšã®å¥ã¢ãžã¥ãŒã«ã«ç§»ããŠãã ããã
RAII: Drop ãã¬ã€ã
RAIIïŒResource Acquisition Is InitializationïŒã§ã¯ããªãœãŒã¹ã®ã©ã€ãã¿ã€ã ãå€ã®ã©ã€ãã¿ã€ã ã«çµã³ä»ããŸãã
Rust 㯠RAII ã䜿ã£ãŠã¡ã¢ãªã管çããŸãããŸããDrop ãã¬ã€ãã䜿ããšãããããã¡ã€ã«ãã£ã¹ã¯ãªãã¿ãããã¯ãªã©ã®ã»ãã®ãªãœãŒã¹ã«ãæ¡åŒµã§ããŸãã
// Copyright 2025 Google LLC // SPDX-License-Identifier: Apache-2.0 pub struct File(std::os::fd::RawFd); impl File { pub fn open(path: &str) -> Result<Self, std::io::Error> { // [...] Ok(Self(0)) } pub fn read_to_end(&mut self) -> Result<Vec<u8>, std::io::Error> { // [...] Ok(b"example".to_vec()) } pub fn close(self) -> Result<(), std::io::Error> { // [...] Ok(()) } } fn main() -> Result<(), std::io::Error> { let mut file = File::open("example.txt")?; println!("content: {:?}", file.read_to_end()?); Ok(()) }
-
èŠèœãšããããç¹:
file.close()ã¯äžåºŠãåŒã³åºãããŠããŸãããåè¬è ãããã«æ°ä»ãããã確èªããŠãã ããã -
ãã¡ã€ã«ãã£ã¹ã¯ãªãã¿ãæ£ããè§£æŸããã«ã¯ãæåŸã®äœ¿çšåŸã«
file.close()ãåŒã³åºããªããã°ãªãããããã«ãšã©ãŒæã®æ©æ return çµè·¯ã§ãåŒã³åºããªããã°ãªããŸããã -
ãŠãŒã¶ãŒã
close()ãåŒã¶ããšã«é Œã代ããã«ãDropãã¬ã€ããå®è£ ããŠãªãœãŒã¹ãèªåçã«è§£æŸã§ããŸããããã«ãããã¯ãªãŒã³ã¢ããã¯Fileå€ã®ã©ã€ãã¿ã€ã ã«çµã³ä»ããããŸãã#![allow(unused)] fn main() { // Copyright 2025 Google LLC // SPDX-License-Identifier: Apache-2.0 impl Drop for File { fn drop(&mut self) { // libc::close(...); println!("file descriptor was closed"); } } } -
Drop::drop()ã¯Resultãè¿ããªãç¹ã«æ³šæããŠãã ããã倱æã¯ãã¹ãŠå éšã§åŠçããããç¡èŠããªããã°ãªããŸãããæšæºã©ã€ãã©ãªã§ã¯ãDropå ã§ FD ãéããéã®ãšã©ãŒã¯é»ã£ãŠç Žæ£ãããŸããå®è£ ã¯æ¬¡ãåç §ããŠãã ãã: https://doc.rust-lang.org/src/std/os/fd/owned.rs.html#169-196 -
Drop::dropã¯ãã€åŒã³åºãããã®ã§ããããïŒéåžžã
main()ã®file倿°ãã¹ã³ãŒããæãããšãïŒreturn æã§ã panic ã«ããå Žåã§ãïŒãdrop()ã¯èªåçã«åŒã³åºãããŸãããã¡ã€ã«ãå¥ã®é¢æ°ã«ã ãŒããããå ŽåïŒ
File::close()ããã®ã±ãŒã¹ã§ãïŒãå€ããããããããã®ã¯mainã§ã¯ãªãããã®é¢æ°ã return ãããšãã§ããå¯Ÿç §çã«ãC++ ã§ã¯ã ãŒãå ã®å€ã«å¯ŸããŠãå ã®ã¹ã³ãŒãã§ãã¹ãã©ã¯ã¿ãå®è¡ãããŸãã
-
ãã¢:
read_to_end()ã®å é ã«panic!("oops")ãæ¿å ¥ããŠå®è¡ããŠãã ãããã¢ã³ã¯ã€ã³ãäžã§ãdrop()ã¯å®è¡ãããŸãã
ããã«èª¿ã¹ã
Drop ãã¬ã€ãã«ã¯ããã 1 ã€éèŠãªå¶çŽããããŸããasync ã§ã¯ãªãããšã§ãã
ããã¯ããã¹ãã©ã¯ã¿ã®äžã§ await ã§ããªãããšãæå³ããŸããããã¯ããœã±ãããããŒã¿ããŒã¹æ¥ç¶ããããã¯å¥ã®ã·ã¹ãã ã«å®äºãéç¥ããªããã°ãªããªãã¿ã¹ã¯ã®ãããªéåæãªãœãŒã¹ãã¯ãªãŒã³ã¢ãããããšãã«ããå¿
èŠã«ãªããŸãã
- ããã«è©³ãã: https://rust-lang.github.io/async-fundamentals-initiative/roadmap/async_drop.html
nightlyã§ã¯ãå®éšçãªAsyncDropãã¬ã€ããå©çšã§ããŸã: https://doc.rust-lang.org/nightly/std/future/trait.AsyncDrop.html
Drop ã¯ã¹ããããããããšããã
ãã¹ãã©ã¯ã¿ãå®è¡ãããªãå ŽåããããŸãã
// Copyright 2025 Google LLC // SPDX-License-Identifier: Apache-2.0 #[derive(Debug)] struct OwnedFd(i32); impl Drop for OwnedFd { fn drop(&mut self) { println!("OwnedFd::drop() called with raw fd: {:?}", self.0); } } impl Drop for TmpFile { fn drop(&mut self) { println!("TmpFile::drop() called with owned fd: {:?}", self.0); // libc::unlink("/tmp/file") // panic!("TmpFile::drop() panics"); } } #[derive(Debug)] struct TmpFile(OwnedFd); impl TmpFile { fn open() -> Self { Self(OwnedFd(2)) } fn close(&self) { panic!("TmpFile::close(): not implemented yet"); } } fn main() { let owned_fd = OwnedFd(1); let file = TmpFile::open(); std::process::exit(0); // std::mem::forget(file); // file.close(); let _ = owned_fd; }
-
Drop ã¯å¿ ãå®è¡ããããšã¯éããŸããã
dropãã¹ããããããã±ãŒã¹ã¯ããã€ããããŸããããšãã°ãããã°ã©ã ãã¯ã©ãã·ã¥ãããçµäºããããDrop å®è£ ãæã€å€ããªãŒã¯ããããããå Žåã§ãã -
std::process::exitãåŒã³åºãããŒãžã§ã³ã§ã¯ãexit()ãdrop()ã¡ãœãããåŒã°ããæ©äŒãäžåäžããã«ããã»ã¹ãå³åº§ã«çµäºããããããTmpFile::drop()ã¯æ±ºããŠå®è¡ãããŸãããclippy::exitlint ã deny ããããšã§ãexitã®å¶çºçãªäœ¿çšãé²ããŸãã
-
std::process::exit(0)ã®è¡ãåé€ãããšããã®åçŽãªã±ãŒã¹ã§ã¯ådrop()ã¡ãœãããé çªã«å®è¡ãããŸãã -
std::mem::forgetã®åŒã³åºãã®ã³ã¡ã³ããå€ããŠã¿ãŠãã ãããäœãèµ·ãããšæããŸãããmem::forget()ã¯æææš©ãåãåãããã¹ãã©ã¯ã¿Drop::drop()ãå®è¡ããã«å€fileããå¿ãããŸããowned_fdã®ãã¹ãã©ã¯ã¿ã¯åŒãç¶ãå®è¡ãããŸãã -
mem::forget()ã®åŒã³åºããåé€ãããã®äžã®file.close()åŒã³åºãã®ã³ã¡ã³ããå€ããŠãã ãããä»åºŠã¯äœãèµ·ãããšæããŸãããããã©ã«ãã®
panic = "unwind"èšå®ã§ã¯ãpanic ãmainã§å§ãŸã£ãå Žåã§ããã¹ã¿ãã¯ã¯åŒãç¶ãã¢ã³ã¯ã€ã³ãããããã¹ãã©ã¯ã¿ã¯å®è¡ãããŸããpanic = "abort"ã§ã¯ããã¹ãã©ã¯ã¿ã¯äžåå®è¡ãããŸããã
-
æåŸã®ã¹ããããšããŠã
TmpFile::drop()å ã®panic!ã®ã³ã¡ã³ããå€ããŠå®è¡ããŠãã ãããã¯ã©ã¹ã«è³ªåããŠã¿ãŸããã: abort ã®åã«ã©ã®ãã¹ãã©ã¯ã¿ãå®è¡ãããŸãããäºé panic ã®åŸã¯ãRust ã¯æ®ãã®ãã¹ãã©ã¯ã¿ãå®è¡ãããããšããã¯ãä¿èšŒããŸããã
- ãã§ã«é²è¡äžã ã£ãäžéšã®ã¯ãªãŒã³ã¢ããã¯å®äºããããšããããŸãïŒããšãã°ãçŸåš drop äžã®å€ã®ãã£ãŒã«ããã¹ãã©ã¯ã¿ãªã©ïŒã
- ããããã¢ã³ã¯ã€ã³ãçµè·¯ã®åŸç¶ã§äºå®ãããŠãããã®ã¯ãå®å šã«ã¹ããããããå¯èœæ§ããããŸãã
- ããããéèŠãªå€éšã¯ãªãŒã³ã¢ããã
drop()ã ãã«é Œãããšã¯ã§ããããŸãäºé panic ã«ãã abort ã§ãã以éã®ãã¹ãã©ã¯ã¿ããŸã£ããå®è¡ãããªããšãä»®å®ã§ããªãããšèšãçç±ã§ãã
-
äžéšã®èšèªã§ã¯ããã¹ãã©ã¯ã¿å ã§ã®äŸå€ãçŠæ¢ãŸãã¯å¶éãããŠããŸããRust ã¯
Drop::dropå ã§ã® panic ãèš±å¯ããŠããŸãããããã¯ã»ãšãã©ã®å Žåããèãã§ã¯ãããŸãããã¢ã³ã¯ã€ã³ãã劚ããäºæž¬äžèœãªã¯ãªãŒã³ã¢ããã«ã€ãªããå¯èœæ§ãããããã§ããdrop bomb ã®ãããªéåžžã«ç¹å¥ãªå¿ èŠãããå Žåãé€ããé¿ããã®ãæåã§ãã -
Drop ã¯ããã»ã¹ã®ã¹ã³ãŒãå ã§ãªãœãŒã¹ãã¯ãªãŒã³ã¢ããããã®ã«ã¯é©ããŠããŸãããããã»ã¹ã®å€éšã§äœããèµ·ããããšã匷ãä¿èšŒããããã®é©åãªææ®µã§ã¯ãããŸããïŒããšãã°ãããŒã«ã«ãã£ã¹ã¯äžã忣ã·ã¹ãã å ã®å¥ã®ãµãŒãã¹äžãªã©ïŒã
-
ããšãã°ã
drop()ã§äžæãã¡ã€ã«ãåé€ããã®ã¯ããã¡ãã®äŸã§ã¯åé¡ãããŸããããå®éã®ããã°ã©ã ã§ã¯ temp file reaper ã®ãããªå€éšã¯ãªãŒã³ã¢ããæ©æ§ãäŸç¶ãšããŠå¿ èŠã«ãªããŸãã -
å¯Ÿç §çã«ã
drop()ã«ãã mutex ã®ã¢ã³ããã¯ã¯ä¿¡é Œã§ããŸããããã¯ããã»ã¹ããŒã«ã«ãªãªãœãŒã¹ã ããã§ããdrop()ãã¹ããããã㊠mutex ãããã¯ããããŸãŸã«ãªã£ãŠããããã»ã¹ã®å€éšã«æ°žç¶çãªåœ±é¿ã¯ãããŸããã
Mutex ãš MutexGuard
以åã®äŸã§ã¯ãRAII ã¯ãã¡ã€ã«ãã£ã¹ã¯ãªãã¿ãŒã®ãããªå
·äœçãªãªãœãŒã¹ã管çããããã«äœ¿ãããŠããŸãããMutex ã§ã¯ãããªãœãŒã¹ãã¯å€ãžã®å¯å€ã¢ã¯ã»ã¹ã§ããå€ã«ã¢ã¯ã»ã¹ããã«ã¯ lock ãåŒã³åºããŸãããããš MutexGuard ãè¿ããããããããããããããš Mutex ã®ããã¯ãèªåçã«è§£é€ãããŸãã
// Copyright 2025 Google LLC // SPDX-License-Identifier: Apache-2.0 use std::sync::Mutex; fn main() { let m = Mutex::new(vec![1, 2, 3]); let mut guard = m.lock().unwrap(); guard.push(4); guard.push(5); println!("{guard:?}"); }
-
Mutexã¯ãããå€ãžã®æä»çãªã¢ã¯ã»ã¹ãå¶åŸ¡ããŸãã以åã® RAII ã®äŸãšã¯ç°ãªããããã§ã®ãªãœãŒã¹ã¯è«ççãªãã®ã§ãããå éšã®ããŒã¿ãžã®äžæçãªæä»çã¢ã¯ã»ã¹ã§ãã -
ãã®æš©å©ã¯
MutexGuardã«ãã£ãŠè¡šãããŸãããã® mutex ã«å¯Ÿããã¬ãŒãã¯ãäžåºŠã« 1 ã€ããååšã§ããŸãããã¬ãŒããçåããŠããéã¯ã&mut Tã¢ã¯ã»ã¹ãæäŸããŸãã -
lock()ã¯&selfãåãåããŸãããå¯å€ã¢ã¯ã»ã¹ãæã€MutexGuardãè¿ããŸãããã㯠interior mutability ã«ãã£ãŠå®çŸãããŠãããåãèªèº«ã®åçšèŠåãå éšçã«ç®¡çããããšã§ã&selfãéãã倿Žãå¯èœã«ããŸãã -
MutexGuardã¯DerefãšDerefMutãå®è£ ããŠãããããèªç¶ã«ã¢ã¯ã»ã¹ã§ããŸããmutex ãããã¯ããã¬ãŒãã&mut Tã®ããã«äœ¿ããŸãã -
mutex ã¯
MutexGuard::drop()ã«ãã£ãŠè§£æŸãããŸããæç€ºçãªã¢ã³ããã¯é¢æ°ãåŒã³åºãããšã¯ãããŸããã
ããããã¬ãŒã
Rust ã«ããã ããããã¬ãŒã ãšã¯ãã¹ã³ãŒããæãããšãã«äœããã® ã¯ãªãŒã³ã¢ããåŠçãè¡ãäžæãªããžã§ã¯ãã§ããMutex ã®å Žåãlock ã¡ãœãã㯠drop æã«ãã¥ãŒããã¯ã¹ãèªåçã«ã¢ã³ããã¯ãã MutexGuard ãè¿ããŸãã
// èäœæš© 2025 Google LLC // SPDX-License-Identifier: Apache-2.0 struct Mutex { is_locked: bool, } struct MutexGuard<'a> { mutex: &'a mut Mutex, } impl Mutex { fn new() -> Self { Self { is_locked: false } } fn lock(&mut self) -> MutexGuard<'_> { self.is_locked = true; MutexGuard { mutex: self } } } impl Drop for MutexGuard<'_> { fn drop(&mut self) { self.mutex.is_locked = false; } }
-
äžã®äŸã¯ãåçŽåãã
Mutexãšãããã«å¯Ÿå¿ããã¬ãŒãã瀺ããŠããŸãã -
ããã¯å®éçšåãã®å®è£ ã§ã¯ãããŸããããäžæ žãšãªãèãæ¹ã瀺ããŠããŸãã
- ã¬ãŒãã¯æä»çã¢ã¯ã»ã¹ã衚ãã
- ãã®
Dropå®è£ ã¯ãã¹ã³ãŒããæãããšãã«ããã¯ãè§£æŸããŸãã
ããã«æãäžãã
ãã®äŸã§ã¯ãä¿è·å¯Ÿè±¡ã®ããŒã¿ãå éšã«ä¿æããªã C++ ã¹ã¿ã€ã«ã®ãã¥ãŒããã¯ã¹ã 瀺ããŠããŸãããã㯠Rust ã§ã¯æ £çšçã§ã¯ãããŸããããããã§ã®ç®ç㯠é©å㪠Rust ã®ãã¥ãŒããã¯ã¹èšèšã瀺ãããšã§ã¯ãªããããããã¬ãŒãã® äžæ žãšãªãèãæ¹ã説æããããšã ãã§ãã
ç°¡æœãã®ããã«ãããã€ãã®æ©èœã¯çãããŠããŸãã
- å®éã®
Mutex<T>ã¯ãä¿è·ãããå€ããã¥ãŒããã¯ã¹å éšã«ä¿æããŸãã
ãã®ç°¡æçãªäŸã§ã¯ãããããã¬ãŒãã®ä»çµã¿ã ãã«çŠç¹ãåœãŠãããã å€ãã®ãã®ãå®å šã«çããŠããŸãã MutexGuardã«å¯ŸããDerefãšDerefMutã«ãã䜿ããããã¢ã¯ã»ã¹ ïŒã¬ãŒãã&TãŸãã¯&mut Tã®ããã«æ±ããããã«ããããšïŒã- å®å
šã«ããããã³ã°ãã
.lock()ã¡ãœãããšãéããããã³ã°ãªtry_lockããªã¢ã³ãã
å®éçšåããã¥ãŒããã¯ã¹ã®äŸãšããŠã Rust ã® std ã©ã€ãã©ãªã«ãã Mutex ã®å®è£
ãåç
§ã§ããŸãããŸãã parking_lot ã¯ã¬ãŒãã® Mutex ãåèã«ãªããŸãã
Drop Bomb: API ã®æ£ããã匷å¶ãã
äžå€æ¡ä»¶ã匷å¶ããAPI ã®èª€ã£ãäœ¿ãæ¹ãæ€åºããã«ã¯ Drop ã䜿ããŸãã ãdrop bombãã¯ãå€ãæç€ºçã«ãã¡ã€ãã©ã€ãºãããªããŸãŸããããããããš panic ããŸãã
ãã®ãã¿ãŒã³ã¯ããã¡ã€ãã©ã€ãºæäœïŒcommit() ã rollback() ãªã©ïŒã Result ãè¿ãå¿
èŠãããå Žåã«ãã䜿ãããŸãããã㯠Drop ãã㯠è¡ããŸããã
// Copyright 2025 Google LLC // SPDX-License-Identifier: Apache-2.0 use std::io::{self, Write}; struct Transaction { active: bool, } impl Transaction { fn start() -> Self { Self { active: true } } fn commit(mut self) -> io::Result<()> { writeln!(io::stdout(), "COMMIT")?; self.active = false; Ok(()) } } impl Drop for Transaction { fn drop(&mut self) { if self.active { panic!("Transaction dropped without commit!"); } } } fn main() -> io::Result<()> { let tx = Transaction::start(); // `tx` ã䜿ã£ãŠãã©ã³ã¶ã¯ã·ã§ã³ãæ§ç¯ãããã®åŸã³ãããããŸãã // panic ã確èªããã«ã¯ã`commit` ã®åŒã³åºããã³ã¡ã³ãã¢ãŠãããŠãã ããã tx.commit()?; Ok(()) }
-
äžéšã®ã·ã¹ãã ã§ã¯ãå€ã¯ãããããããåã«ç¹å®ã® API ã«ãã£ãŠ ãã¡ã€ãã©ã€ãºãããªããã°ãªããŸããã
ããšãã°ã
Transactionã¯ã³ããããŸãã¯ããŒã«ããã¯ããå¿ èŠããã å ŽåããããŸãã -
drop bomb ã¯ã
Transactionã®ãããªå€ãæªå®äºã®ç¶æ ã®ãŸãŸé»ã£ãŠ ãããããããªãããšãä¿èšŒããŸãããã©ã³ã¶ã¯ã·ã§ã³ãæç€ºçã« ãã¡ã€ãã©ã€ãºãããŠããªãå ŽåïŒããšãã°commit()ããŠããªãå ŽåïŒã ãã¹ãã©ã¯ã¿ã¯ panic ããŸãã -
ãã¡ã€ãã©ã€ãºæäœïŒ
commit()ãªã©ïŒã¯éåžžãselfãå€ã§åãåããŸãã ããã«ããããã©ã³ã¶ã¯ã·ã§ã³ããã¡ã€ãã©ã€ãºãããåŸã¯ãå ã®ãªããžã§ã¯ãã ãã䜿ããªããªããŸãã -
ãã®ãã¿ãŒã³ã䜿ãäžè¬çãªçç±ã¯ãã¯ãªãŒã³ã¢ããã
Dropã§è¡ããªã å Žåã§ãã倱æããå¯èœæ§ãããããŸãã¯éåæã§ããããšããã®çç±ã§ãã -
ãã®ãã¿ãŒã³ã¯å ¬é API ã§ãé©åã§ãããã©ã³ã¶ã¯ã·ã§ã³ãªããžã§ã¯ãã æç€ºçã«ãã¡ã€ãã©ã€ãºãå¿ãããšãã«ããŠãŒã¶ãŒãæ©ã段éã§ãã°ã èŠã€ããå©ãã«ãªããŸãã
-
ã¯ãªãŒã³ã¢ããã
Dropã§å®å šã«è¡ãããªãããããã°ãã«ãã§ã®ã¿ panic ããããšãéžã¶ API ããããŸãããããé©åãã©ããã¯ãAPI ã匷å¶ããªããã° ãªããªãä¿èšŒã«äŸåããŸãã -
誀çšãé»ã£ãŠèŠéããããããšã§éå€§ãªæ£ãããã»ãã¥ãªãã£äžã®åé¡ã çããå ŽåããªãªãŒã¹ãã«ãã§ panic ããã®ã¯åŠ¥åœã§ãã
-
質å: ãªã
Transactionã®äžã«activeãã©ã°ãå¿ èŠãªã®ã§ããããããªãdrop()ã¯ç¡æ¡ä»¶ã« panic ããŠã¯ãããªãã®ã§ãããããæåŸ ãããçã:
commit()ã¯selfãå€ã§åãåãããã®éã«drop()ã å®è¡ããããããpanic ããŠããŸããŸãã
ããã«èª¿ã¹ã
é©åãªåŸå§æ«ã匷å¶ãããã誀ã£ãŠããããããŠããŸãããšãé²ãã ããã é¢é£ãã¿ãŒã³ãããã€ããããŸãã
drop_bombcrate:.defuse()ã§æç€ºçã«ç¡å¹åããªãéããããããããããš panic ããå°ã㪠ãŠãŒãã£ãªãã£ã§ãããããã°ãã«ãã§ã®ã¿æå¹ã«ãªãDebugDropBombããªã¢ã³ããä»å±ããŠããŸãã
ãããããã : std::mem::forget ã䜿ã
// Copyright 2025 Google LLC // SPDX-License-Identifier: Apache-2.0 use std::io::{self, Write}; struct Transaction; impl Transaction { fn start() -> Self { Transaction } fn commit(self) -> io::Result<()> { writeln!(io::stdout(), "COMMIT")?; // Drop ãæ±ºããŠå®è¡ãããªãããã«ããŠãããããã ãè§£é€ããã std::mem::forget(self); Ok(()) } } impl Drop for Transaction { fn drop(&mut self) { // ãããããããããã ã panic!("commit ãããã« Transaction ããããããããŸãã!"); } } fn main() -> io::Result<()> { let tx = Transaction::start(); // `tx` ã䜿ã£ãŠãã©ã³ã¶ã¯ã·ã§ã³ãæ§ç¯ãããã®åŸ commit ããã // ãããã¯ã確èªããã«ã¯ `commit` ã®åŒã³åºããã³ã¡ã³ãã¢ãŠãããã tx.commit()?; Ok(()) }
ãã®äŸã§ã¯åã®ã¹ã©ã€ãã®ãã©ã°ãåãé€ããdrop ã¡ãœãããç¡æ¡ä»¶ã« panic ããããã«ããŠããŸããæåãã commit ã§ãã® panic ãé¿ããããã«ãcommit ã¡ãœããã¯ãã©ã³ã¶ã¯ã·ã§ã³ã®æææš©ãåãåãã std::mem::forget ãåŒã³åºãããã«ãªã£ãŠããŸããããã«ãã Drop::drop() ã¡ãœããã¯å®è¡ãããŸããã
å¿ããããå€ããé垞㯠drop() å®è£
ã§è§£æŸãããããŒã確ä¿ãããã¡ã¢ãªãææããŠããå Žåããã®çµæã® 1 ã€ã¯ã¡ã¢ãªãªãŒã¯ã§ããäžã®äŸã® Transaction ã§ã¯ãããŒãã¡ã¢ãªãäžåææããŠããªãããããã®åé¡ã¯èµ·ããŸããã
mem::forget() ãæŠè¡çã«äœ¿ãããšã§ãå®è¡æãã©ã°ãäžèŠã«ã§ããŸãããã©ã³ã¶ã¯ã·ã§ã³ã® commit ãæåãããšãã¯ããã®å€ã«å¯Ÿã㊠std::mem::forget ãåŒã³åºãããšã§ãããããã ãè§£é€ã§ãããã® Drop å®è£
ã¯å®è¡ãããªããªããŸãã
forget 颿°ãš drop 颿°
以äžã¯ãdrop() 颿°ãš forget() 颿°ã®ã·ã°ããã£ã§ã:
// èäœæš© 2025 Google LLC // SPDX-License-Identifier: Apache-2.0 // std::mem::forget fn forget<T>(t: T) { let _ = std::mem::ManuallyDrop::new(t); } // std::mem::drop fn drop<T>(_x: T) {}
-
mem::forget()ãšmem::drop()ã¯ã©ã¡ããå€tã®æææš©ãåãåããŸãã -
åã颿°ã·ã°ããã£ãæã£ãŠããŸããããã®å¹æã¯æ£å察ã§ã:
-
forget()ã¯ManuallyDropã䜿çšããŠããã¹ãã©ã¯ã¿Drop::drop()ãåŒã³åºãããã®ãé²ããŸããããã¯ãdrop bomb ãå®è£ ããå Žåãããã®ä»ãã¹ãã©ã¯ã¿ã®æ¯ãèãã ç¡å¹ã«ãããå Žåã«æçšã§ãã
ãã ãæ³šæãå¿ èŠã§ããããŒãã«ç¢ºä¿ãããã¡ã¢ãªããã¡ã€ã«ãã³ãã«ãªã©ã ãã®å€ãæä»çã«ææããŠãããªãœãŒã¹ã¯ãå°éäžèœãªç¶æ ã®ãŸãŸæ®ãããã§ãã
-
drop()ã¯ãå€ãç Žæ£ããããã®äŸ¿å©é¢æ°ã§ããtã¯é¢æ°ã« ã ãŒãããããããèªåçã«ãããããããåŒã³åºãå ã®é¢æ°ãè¿ãåã« ãã®Drop::drop()å®è£ ãåŒã³åºãããŸãã
-
ã¹ã³ãŒãã¬ãŒã
ã¹ã³ãŒãã¬ãŒã㯠Drop ãã¬ã€ãã䜿ã£ãŠãã¹ã³ãŒããæãããšãã«ãã¢ã³ã¯ã€ã³ãäžã§ãã£ãŠãèªåçã«ã¯ãªãŒã³ã¢ããã³ãŒããå®è¡ããŸãã
// Copyright 2025 Google LLC // SPDX-License-Identifier: Apache-2.0 use scopeguard::{ScopeGuard, guard}; use std::fs::{self, File}; use std::io::Write; fn download_successful() -> bool { // [...] true } fn main() { let path = "download.tmp"; let mut file = File::create(path).expect("äžæãã¡ã€ã«ãäœæã§ããŸãã"); // ãã¡ã€ã«äœæã®çŽåŸã«ã¯ãªãŒã³ã¢ãããèšå®ãã let cleanup = guard(path, |path| { println!("ããŠã³ããŒãã«å€±æããããåé€ããŸã: {:?}", path); let _ = fs::remove_file(path); }); writeln!(file, "partial data...").unwrap(); if download_successful() { // ããŠã³ããŒãã«æåãããããã¡ã€ã«ãæ®ã let path = ScopeGuard::into_inner(cleanup); println!("ããŠã³ããŒã '{path}' ãå®äºããŸãã!"); } // ãã以å€ã®å Žåã¯ãã¬ãŒããå®è¡ãããŠãã¡ã€ã«ãåé€ãã }
-
ãã®äŸã¯ããŠã³ããŒãã®ã¯ãŒã¯ãããŒãã¢ãã«åãããã®ã§ããæåã«äžæãã¡ã€ã«ãäœæãããã®åŸãããŠã³ããŒãã倱æããå Žåã«ãã®ãã¡ã€ã«ãåé€ãããããã¹ã³ãŒãã¬ãŒãã䜿ããŸãã
-
scopeguardã¯ã¬ãŒãã䜿ããšãã«ã¹ã¿ã ã®Dropå®è£ ãæã€ç¬èªã®åãå®çŸ©ããªããŠããåçºã®DropããŒã¹ã®ã¯ãªãŒã³ã¢ãããç°¡åã«å®çŸ©ã§ããŸãã -
ã¬ãŒãã¯ãã¡ã€ã«äœæã®çŽåŸã«äœæãããããã
writeln!()ã倱æããŠããã¡ã€ã«ã¯ç¢ºå®ã«ã¯ãªãŒã³ã¢ãããããŸãããã®é åºã¯æ£ããã®ããã«äžå¯æ¬ ã§ãã -
guard()ã¯ScopeGuardã€ã³ã¹ã¿ã³ã¹ãäœæããŸããããã¯ãŠãŒã¶ãŒå®çŸ©ã®å€ïŒãã®å Žåã¯pathïŒãšãåŸã§ãã®å€ãåãåãã¯ãªãŒã³ã¢ããçšã¯ããŒãžã£ãåãåããŸãã -
ã¬ãŒãã®ã¯ããŒãžã£ã¯ã
ScopeGuard::into_innerã§ ç¡å¹å ãããªãéããã¹ã³ãŒãçµäºæã«å®è¡ãããŸãïŒå€ãåãåºãããšã§ãdrop æã«ã¬ãŒããäœãããªããªããŸãïŒãæåãã¹ã§ã¯into_innerãåŒã³åºããããã¬ãŒãã¯ãã¡ã€ã«ãåé€ããŸããã -
ã¹ã³ãŒãã¬ãŒã㯠Go ã®
deferæ©èœã«äŒŒãŠããŸãã -
ãã®ãã¿ãŒã³ã¯ã倱ææã®ã¯ãªãŒã³ã¢ãããã®ã·ããªãªã«æé©ã§ãæåãã¹ãæç€ºçã«éžã°ããªãéããããã©ã«ãã§ã¯ãªãŒã³ã¢ãããå®è¡ãã¹ãå Žåã«é©ããŠããŸãã
-
ãã®ãã¿ãŒã³ã¯ããªãœãŒã¹ãªããžã§ã¯ãã®ã¯ãªãŒã³ã¢ããæŠç¥ãèªåã§å¶åŸ¡ã§ããªãå Žåã«ãæçšã§ãããã®äŸã§ã¯ã
File::drop()ã¯ãã¡ã€ã«ãéããŸãããåé€ã¯ããŸããã -
scopeguardã¯ã¬ãŒãã¯ãStrategyãã¬ã€ããä»ããã¯ãªãŒã³ã¢ããæŠç¥ããµããŒãããŠããŸããã¬ãŒããã¢ã³ã¯ã€ã³ãæã®ã¿ããŸãã¯æåæã®ã¿ã«å®è¡ããããéžã¹ããããåã«åžžã«å®è¡ããã ãã§ã¯ãããŸããã
Drop: Option
// Copyright 2025 Google LLC // SPDX-License-Identifier: Apache-2.0 struct File(Option<Handle>); impl File { fn open(path: &'static str) -> std::io::Result<Self> { Ok(Self(Some(Handle { path }))) } fn write(&mut self, data: &str) -> std::io::Result<()> { // `Handle` ãååŸããã«ã¯ã`Option` ãçµç±ããå¿ èŠããããŸãã // ããããŠåããŠäœ¿ããããã«ãªããŸãã let handle = self.0.as_ref().unwrap(); println!("write '{data}' to file '{}'", handle.path); Ok(()) } } impl Drop for File { fn drop(&mut self) { let handle = self.0.take().unwrap(); handle.close(); } } struct Handle { path: &'static str, } impl Handle { fn close(self) { println!("Closing {}", self.path); } } fn main() -> std::io::Result<()> { let mut file = File::open("foo.txt")?; file.write("hello")?; Ok(()) }
-
ãã®äŸã§ã¯ã
Dropå®è£ ã®äžã§å éšã®Handleã«å¯ŸããŠcloseãåŒã³åºãããã®ã§ãããcloseã¯Handleã®æææš©ãå¿ èŠãšããŸããéåžžã¯ããã¯ã§ããŸããããªããªããdropã§ã¯Fileãªããžã§ã¯ãã®æææš©ãåãåããªãããã ãã£ãŒã«ãããå€ãã ãŒãã§ããªãããã§ãã -
HandleãOptionã§å ãããšã§ãå¯å€åç §ãéããŠãã£ãŒã«ãããå€ãã ãŒã ã§ããããã«ãªããŸãã -
äž»ãªæ¬ ç¹ã¯äœ¿ãåæã§ãã
Optionã«ãããšãè«ççã«ã¯Noneãèµ·ããããªãå Žæã§ããSomeãšNoneã®äž¡æ¹ã®ã±ãŒã¹ãæ±ããªããã°ãªããŸãããRust ã®åã·ã¹ãã ã§ã¯Fileãšãã®Handleã®éã®ãã®é¢ä¿ã衚çŸã§ããªãããã äž¡æ¹ã®ã±ãŒã¹ãæåã§åŠçããŸãã
ããã«èª¿ã¹ã
Option ã®ä»£ããã« ManuallyDrop ã䜿ãããšãã§ããŸããããã¯ãRust ãå€ã«å¯Ÿã㊠Drop ãåŒã³åºããªãããã«ããããšã§ èªåç Žæ£ãæå¶ãããã®ã§ãåŸå§æ«ã¯èªåã§åŠçããªããã°ãªããŸããã
åã®ã¹ã©ã€ãã®scopeguard ã®äŸã§ã¯ã ManuallyDrop ã§ Option ã眮ãæããããšã§ãå€ãåžžã«ååšããã¯ãã®å Žæã§ None ãæ±ããã«æžãæ¹æ³ã瀺ããŠããŸãã
ãã®ãããªèšèšã§ã¯éåžžãManuallyDrop<Handle> ã®é£ã«å¥ã®ãã©ã°ã眮ããŠ ç Žæ£ç¶æ
ã远跡ããããã«ãã£ãŠãã³ãã«ããã§ã«æåã§æ¶è²»ããããã©ããã ææ¡ã§ããŸãã
æ¡åŒµãã¬ã€ã
å€éšã®åãæ°ããã¡ãœããã§æ¡åŒµããããšäŸ¿å©ãªå ŽåããããŸããããšãã°ã ã¡ãœããåŒã³åºãæ§æ s.is_palindrome() ã䜿ã£ãŠãæååãåæãã©ããã ã³ãŒãã§å€å®ã§ããããã«ãããããšãã£ãå Žåã§ãã
ãã®å Žåãimpl ãããã¯ã䜿ããããªããããããŸããã
// Copyright 2025 Google LLC // SPDX-License-Identifier: Apache-2.0 // ð ïžâ impl str { pub fn is_palindrome(&self) -> bool { self.chars().eq(self.chars().rev()) } }
ããããRust ã³ã³ãã€ã©ã¯ãããèš±å¯ããŸããããšã¯ããããã®å¶çŽã¯ æ¡åŒµãã¬ã€ã ãã¿ãŒã³ ã䜿ãããšã§åé¿ã§ããŸãã
-
Rust ã®ã¢ã€ãã ïŒãã¬ã€ãã§ãåã§ãïŒã¯ã次ã®ããã«åŒã°ããŸãã
- çŸåšã®ã¯ã¬ãŒãã§å®çŸ©ãããŠããªãå Žå㯠foreign
- çŸåšã®ã¯ã¬ãŒãã§å®çŸ©ãããŠããå Žå㯠local ãã®åºå¥ã¯ãã³ããŒã¬ã³ã¹ãšãªãŒãã¡ã³ã«ãŒã« ã«å€§ããé¢ãããŸãããã®ç¹ã¯ã ã³ãŒã¹ã®ãã®ã»ã¯ã·ã§ã³ã§è©³ããèŠãŠãããŸãã
-
ãã®äŸãã³ã³ãã€ã«ããŠãåºåãããã³ã³ãã€ã©ãšã©ãŒã瀺ããŠãã ããã
ã³ã³ãã€ã©ã®ãšã©ãŒã¡ãã»ãŒãžããã©ã®ããã«æ¡åŒµãã¬ã€ããã¿ãŒã³ãžãšå°ããŠããã ã®ãã匷調ããŠãã ããã
-
Rust ã«ãããå€ãã®åã·ã¹ãã äžã®å¶çŽããææ§ã ãé²ãããšãç®çãšããŠãã ããšã説æããŠãã ããã
ããå€éšã®åã«æ°ããåºæã¡ãœãããå®çŸ©ã§ãããšããããã©ããªãã§ããããã äŸåé¢ä¿ããªãŒå ã®ç°ãªãã¯ã¬ãŒãããåãå€éšã®åã«å¯ŸããŠåãååã®ç°ãªã ã¡ãœãããå®çŸ©ããŠããŸããããããŸããã
ææ§ããå ¥ã蟌ãäœå°ããããªãããããè§£æ¶ããæ¹æ³ãå¿ èŠã«ãªããŸãã ææ§ãã®è§£æ¶ãæé»çã«è¡ããããšãé©ããããªããããã¯äºæããªãæåã« ã€ãªããå¯èœæ§ããããŸããææ§ãã®è§£æ¶ãæç€ºçã«è¡ãããå Žåãã³ãŒããèªã éçºè ã®èªç¥è² è·ãå¢ããå¯èœæ§ããããŸãã
ããã«ãããã¯ã¬ãŒããå€éšã®åã«æ°ããåºæã¡ãœãããå®çŸ©ãããã³ã«ãæç€ºçãª ææ§ãã®è§£æ¶ãå°å ¥ããããåŸãªããªããããããªãã® ã³ãŒãã§ã³ã³ãã€ã«ãšã©ãŒã çºçããå¯èœæ§ããããŸãã
Rust ã¯ãå€éšã®åã«æ°ããåºæã¡ãœãããå®çŸ©ããããšèªäœãçŠæ¢ããããšã§ã ãã®åé¡ãã®ãã®ãé¿ããããšã«ããŠããŸãã
-
ä»ã®èšèªïŒäŸ: KotlinãC#ãSwiftïŒã§ã¯ãæ¢åã®åã«ã¡ãœããã远å ã§ããŸãã ããã¯ãã°ãã°ãæ¡åŒµã¡ãœããããšåŒã°ããŸããããã«ãããæœåšçãªææ§ãã 倧åçãªæšè«ã®å¿ èŠæ§ã«é¢ããŠãç°ãªããã¬ãŒããªããçããŸãã
å€éšåã®æ¡åŒµ
æ¡åŒµãã¬ã€ããšã¯ãäž»ãªç®çãå€éšåã«æ°ããã¡ãœããã远å ããããšã§ãããããŒã«ã«ãªãã¬ã€ãå®çŸ©ã§ãã
// Copyright 2025 Google LLC // SPDX-License-Identifier: Apache-2.0 mod ext { pub trait StrExt { fn is_palindrome(&self) -> bool; } impl StrExt for str { fn is_palindrome(&self) -> bool { self.chars().eq(self.chars().rev()) } } } fn main() { // æ¡åŒµãã¬ã€ããã¹ã³ãŒãã«å°å ¥ã... pub use ext::StrExt as _; // ...ãã®åŸããããã®ã¡ãœãããããããåºæã¡ãœããã§ãããã®ããã«åŒã³åºã assert!("dad".is_palindrome()); assert!(!"grandma".is_palindrome()); }
-
Extæ¥å°ŸèŸã¯ãæ £äŸãšããŠæ¡åŒµãã¬ã€ãã®ååã«ä»ããããŸããããã¯ããã®ãã¬ã€ããäž»ã«æ¡åŒµã®ç®çã§äœ¿ãããããšããããã£ãŠãããå®çŸ©ããŠãã crate ã®å€éšã§å®è£ ããããšãæå³ããŠããªãããšã瀺ããŸãã
åœåèŠåã«é¢ããæš©åšããæ å ±æºãšããŠããExtension TraitãRFC ãåç §ããŠãã ããã
-
å€éšåã«å¯Ÿããæ¡åŒµãã¬ã€ãã®å®è£ ã¯ããã¬ã€ãèªäœãšåã crate å ã«ãªããã°ãªããŸãããããã§ãªããšãRust ã® å€å ã«ãŒã« ã«é»ãŸããŸãã
-
æ¡åŒµãã¬ã€ãã®ã¡ãœãããåŒã³åºããšãã¯ããã®æ¡åŒµãã¬ã€ããã¹ã³ãŒãå ã«ãªããã°ãªããŸããã
察å¿ããæ¡åŒµãã¬ã€ããã¹ã³ãŒãå ã«ãªããŸãŸæ¡åŒµã¡ãœãããåŒã³åºãããšãããšãã«çºçããã³ã³ãã€ã©ãšã©ãŒã確èªããã«ã¯ãäŸã®
useæãã³ã¡ã³ãã¢ãŠãããŠãã ããã -
äžã®äŸã§ã¯ãã»ãã«ã€ã³ããŒãããããã¬ã€ããšã®ååè¡çªã®å¯èœæ§ãæå°éã«æããããã«ãã¢ã³ããŒã¹ã³ã¢ã€ã³ããŒãïŒ
use ext::StringExt as _ïŒã䜿ã£ãŠããŸããã¢ã³ããŒã¹ã³ã¢ã€ã³ããŒãã§ã¯ããã®ãã¬ã€ãã¯ã¹ã³ãŒãå ã«ãããã®ãšèŠãªããããã®ãã¬ã€ããå®è£ ããŠããåã«å¯ŸããŠãã®ã¡ãœãããåŒã³åºããŸããäžæ¹ããã® ã·ã³ãã« èªäœã«ã¯çŽæ¥ã¢ã¯ã»ã¹ã§ããŸãããããã«ãããããšãã°ãã®ãã¬ã€ãã
whereå¥ã§äœ¿ãããšã¯ã§ããŸãããæ¡åŒµãã¬ã€ãã¯
whereå¥ã§äœ¿ãããšãæå³ããŠããªããããæ £äŸãšããŠã¢ã³ããŒã¹ã³ã¢ã€ã³ããŒãã§ã€ã³ããŒããããŸãã
ã¡ãœãã解決ã®ç«¶å
åºæã¡ãœãããšæ¡åŒµã¡ãœããã®éã§ååã®ç«¶åããããšãäœãèµ·ããã§ããããïŒ
// Copyright 2025 Google LLC // SPDX-License-Identifier: Apache-2.0 mod ext { pub trait CountOnesExt { fn count_ones(&self) -> u32; } impl CountOnesExt for i32 { fn count_ones(&self) -> u32 { let value = *self; (0..32).filter(|i| ((value >> i) & 1i32) == 1).count() as u32 } } } fn main() { pub use ext::CountOnesExt; // ã©ã® `count_ones` ã¡ãœãããåŒã³åºãããã§ããããïŒ // `CountOnesExt` ã®ãã®ã§ããïŒ ãããšã `i32` ã®åºæã¡ãœããã§ããïŒ assert_eq!((-1i32).count_ones(), 32); }
-
å€éšã®åã«ãæ°ããããŒãžã§ã³ã§ãç§ãã¡ã®æ¡åŒµã¡ãœãããšåãååã® æ°ããåºæã¡ãœããã远å ãããããšããããŸãã
質å: äžã®äŸã§ã¯äœãèµ·ããã§ããããïŒ ã³ã³ãã€ã©ãšã©ãŒã«ãªãã§ããããïŒ 2 ã€ã®ã¡ãœããã®ããããã«ãããé«ãåªå é äœãäžããããã§ããããïŒ ããã¯ã©ã¡ãã§ããããïŒ
CountOnesExt::count_onesã®æ¬äœã«panic!("Extension trait");ã远å ããŠã ã©ã¡ãã®ã¡ãœãããåŒã³åºãããŠããã®ããæç¢ºã«ããŠãã ããã -
Rust èšèªã®ãŠãŒã¶ãŒãããããå Žåã«ã©ã®ã¡ãœããã䜿ãããæåã§æå®ããªããŠã ããããã«ãã¡ãœãããæåã«ã©ã®ããã«ãéžã°ããããã«ã¯ åªå é äœã®ä»çµã¿ããããŸã:
- äžå€ïŒ
&selfïŒãå - åºæïŒåã®
implãããã¯ã§å®çŸ©ãããã¡ãœããïŒããã¬ã€ãïŒtrait ã® impl ã«ãã£ãŠè¿œå ãããã¡ãœããïŒããå ã
- åºæïŒåã®
- å¯å€ïŒ
&mut selfïŒã次- åºæããã¬ã€ãããå ã åãååã®ãã¹ãŠã®ã¡ãœãããããããç°ãªãå¯å€æ§ãæã¡ããã€ åºæã¡ãœãããŸãã¯ãã¬ã€ãã¡ãœããã®ãããããšããŠå®çŸ©ãããŠããŠã éè€ããªããã°ãã³ã³ãã€ã©ã«ãšã£ãŠå€å®ã¯å®¹æã«ãªããŸãã ãã ããããã¯ãŠãŒã¶ãŒã«ããçšåºŠã®ææ§ãããããããŸããäŸåããŠãã ã¡ãœããããªãæåŸ ã©ããã®æ¯ãèããããªãã®ãåããããæ··ä¹±ãããã ãããŸãããå¯èœã§ããã°ããã®ä»çµã¿ã«é Œãã®ã§ã¯ãªãååã®ç«¶åã é¿ããŠãã ããã
宿Œ:
CountOnesExt::count_onesã®ã·ã°ããã£ãšå®è£ ãfn count_ones(&mut self) -> u32ã«å€æŽããããã«åãããŠåŒã³åºãã ä¿®æ£ããŠãã ãã:#![allow(unused)] fn main() { // Copyright 2025 Google LLC // SPDX-License-Identifier: Apache-2.0 assert_eq!((&mut -1i32).count_ones(), 32); }åºæã¡ãœããã§ã¯ãªã
CountOnesExt::count_onesãåŒã³åºãããŸããããã¯ã&mut selfã®ã»ãããåºæã¡ãœããã§äœ¿ããã&selfãããåªå é äœã é«ãããã§ããåãåã«å¯ŸããŠäžå€ã®åºæã¡ãœãããšå¯å€ã®ãã¬ã€ãã¡ãœãããååšããå Žåã åŒã³åºãç®æã§ã©ã¡ãã䜿ãããæå®ã§ããŸãã
(&<value>).count_ones()ã䜿ã£ãŠ äžå€ã®ïŒããé«ãåªå é äœã®ïŒã¡ãœãããååŸãããã(&mut <value>).count_ones()åŠçã«ã¯ãã¡ãœãã解決 ã®è©³çްã«ã€ã㊠Rust ãªãã¡ã¬ã³ã¹ãåç §ãããã æ¡å ããŠãã ããã
- äžå€ïŒ
-
æ¡åŒµãã¬ã€ãã®ã¡ãœãããšåºæã¡ãœããã®éã§ååã®ç«¶åãèµ·ããªãããã«ã㊠ãã ãããRust ã®ã¡ãœãã解決ã¢ã«ãŽãªãºã ã¯è€éã§ãããããªãã®ã³ãŒãã® ãŠãŒã¶ãŒãé©ãããå¯èœæ§ããããŸãã
ããã«è©³ãã
- Rust ã®ã¡ãœãã解決ã¢ã«ãŽãªãºã ã§äœ¿ãããåªå
é äœæ€çŽ¢ãšãèªå
Derefã® çžäºäœçšã¯ãäž»ã«ãã¯ãçæã³ãŒãã®æèã«ãããŠãstable ããŒã«ãã§ãŒã³äžã§ ç¹æ®å ããšãã¥ã¬ãŒãããããã«å©çšã§ããŸããå ·äœçãªè©³çްã«ã€ããŠã¯ âAutoref Specializationâ ãåç §ããŠãã ããã
ãã¬ã€ãã¡ãœããã®è¡çª
åãåã«å®è£ ããã 2 ã€ã®ç°ãªããã¬ã€ãã¡ãœããã®éã§ååã®è¡çªãèµ·ãããšãã©ããªãã§ããããïŒ
// Copyright 2025 Google LLC // SPDX-License-Identifier: Apache-2.0 mod ext { pub trait Ext1 { fn is_palindrome(&self) -> bool; } pub trait Ext2 { fn is_palindrome(&self) -> bool; } impl Ext1 for str { fn is_palindrome(&self) -> bool { self.chars().eq(self.chars().rev()) } } impl Ext2 for str { fn is_palindrome(&self) -> bool { self.chars().eq(self.chars().rev()) } } } pub use ext::{Ext1, Ext2}; // ã©ã®ã¡ãœãããåŒã³åºãããã§ããããïŒ // `Ext1` ã®ãã®ïŒ ãããšã `Ext2` ã®ãã®ïŒ fn main() { assert!("dad".is_palindrome()); }
-
æ¡åŒµããŠãããã¬ã€ãããæ°ããããŒãžã§ã³ã§ãããªãã®æ¡åŒµã¡ãœãããšåãååã®æ°ãããã¬ã€ãã¡ãœããã远å ããå¯èœæ§ããããŸãããããã¯ãåãåã«å¯Ÿããå¥ã®æ¡åŒµãã¬ã€ãããããªãèªèº«ã®æ¡åŒµã¡ãœãããšååãè¡çªããã¡ãœãããå®çŸ©ããå¯èœæ§ããããŸãã
åããã: äžã®äŸã§ã¯äœãèµ·ããã§ããããïŒ ã³ã³ãã€ã©ãšã©ãŒã«ãªãã§ããããïŒ 2 ã€ã®ã¡ãœããã®ã©ã¡ããã«ããé«ãåªå é äœãäžããããã§ããããïŒ ããã¯ã©ã¡ãã§ããããïŒ
-
ã³ã³ãã€ã©ã¯ãã©ã®ã¡ãœãããåŒã³åºãã¹ãã倿ã§ããªãããããã®ã³ãŒããæåŠããŸãã
Ext1ã«ãExt2ã«ããããäžæ¹ããé«ãåªå é äœã¯ãããŸããããã®è¡çªã解決ããã«ã¯ãã©ã®ãã¬ã€ãã䜿ãããã®ããæç€ºããå¿ èŠããããŸãã
宿Œ:
"dad".is_palindrome()ã®ä»£ããã«ãExt1::is_palindrome("dad")ãŸãã¯Ext2::is_palindrome("dad")ãåŒã³åºããŸããã·ã°ããã£ãããè€éãªã¡ãœããã§ã¯ãããæç€ºç㪠å®å šä¿®é£Ÿæ§æ ã䜿ãå¿ èŠãããå ŽåããããŸãã
-
宿Œ:
"dad".is_palindrome()ã<str as Ext1>::is_palindrome("dad")ãŸãã¯<str as Ext2>::is_palindrome("dad")ã«çœ®ãæããŸãã
ä»ã®ãã¬ã€ããæ¡åŒµãã
åãšåæ§ã«ãå€éšãã¬ã€ããæ¡åŒµãããå ŽåããããŸããç¹ã«ã ãããã¬ã€ããå®è£ ãã ãã¹ãŠ ã®åã«æ°ããã¡ãœããã远å ãããå Žåã§ãã
// èäœæš© 2025 Google LLC // SPDX-License-Identifier: Apache-2.0 mod ext { use std::fmt::Display; pub trait DisplayExt { fn quoted(&self) -> String; } impl<T: Display> DisplayExt for T { fn quoted(&self) -> String { format!("'{}'", self) } } } pub use ext::DisplayExt as _; assert_eq!("dad".quoted(), "'dad'"); assert_eq!(4.quoted(), "'4'"); assert_eq!(true.quoted(), "'true'");
-
äžåºŠã« è€æ° ã®åãžæ°ããæ¯ãèãã远å ããç¹ã匷調ããŠãã ããã
.quoted()ã¯æååã¹ã©ã€ã¹ãæ°å€ãçåœå€ã«å¯ŸããŠåŒã³åºããŸãããããã¯ãã¹ãŠDisplayãã¬ã€ããå®è£ ããŠããããã§ãããã®çš®ã®æ¡åŒµãã¬ã€ããã¿ãŒã³ã§ã¯ã ãã©ã³ã±ããå®è£ ã䜿ããŸãã
ãã©ã³ã±ããå®è£ ã¯ã
implãããã¯ã§æå®ããããã¬ã€ãå¢çãæºãããã¹ãŠã® åTã«å¯ŸããŠãã®ãã¬ã€ããå®è£ ãããã®ã§ãããã®å Žåãå¯äžã®èŠä»¶ã¯TãDisplayãã¬ã€ããå®è£ ããŠããããšã§ãã -
åŠçã®æ³šæã
DisplayExt::quotedã®å®è£ ã«åããŠãã ãããTã«ã€ããŠã¯ãDisplayãå®è£ ããŠããããšä»¥å€ã«äœãä»®å®ã§ããŸãããããžãã¯ã¯ãã¹ãŠãDisplayã®ã¡ãœããããã»ãã®ãã¬ã€ããå¿ èŠãšããªã颿°/ãã¯ãã® ã©ã¡ããã䜿ããªããã°ãªããŸãããããšãã°ã
Tã«å¯ŸããŠformat!ã¯äœ¿ããŸããã.to_uppercase()㯠åŒã³åºããŸãããå¿ ãããStringãšã¯éããªãããã§ããTã«è¿œå ã®ãã¬ã€ãå¢çãå°å ¥ããããšãã§ããŸããããããããš ãã®æ¡åŒµãã¬ã€ããå©çšã§ããåã®éåãå¶éãããŸãã -
æ £äŸãšããŠãæ¡åŒµãã¬ã€ãã®ååã¯ãæ¡åŒµå¯Ÿè±¡ã®ãã¬ã€ãåã®åŸãã«
Extæ¥å°ŸèŸãä»ãããã®ã«ããŸããäžã®äŸã§ã¯DisplayExtã§ãã -
æšæºã©ã€ãã©ãªã®ãã¬ã€ãã«æ°ããæ©èœã远å ããã¯ã¬ãŒãã ãããŸãã
-
itertoolsã¯ã¬ãŒãã¯ãIteratorãæ¡åŒµããItertoolsãã¬ã€ãã æäŸããŸããããã¯interleaveãuniqueãªã©ãå€ãã® ã€ãã¬ãŒã¿ã¢ããã¿ã远å ããŸããã¡ãœãããã§ãŒã³ã§æ§ç¯ããã ã€ãã¬ãŒã¿ãã€ãã©ã€ã³ã«å¯ŸããŠãæ°ããã¢ã«ãŽãªãºã äžã®æ§æèŠçŽ ãæäŸããŸãã -
futuresã¯ã¬ãŒãã¯ãFutureãã¬ã€ããæ¡åŒµããFutureExtãã¬ã€ããæäŸããæ°ããã³ã³ãããŒã¿ããã«ããŒã¡ãœããã远å ããŸãã
-
ããã«æãäžãã
-
æ¡åŒµãã¬ã€ãã¯ãå®å®çã¡ãœãããšå®éšçã¡ãœãããã©ã€ãã©ãªãåºå¥ããããã«ã 䜿ããŸãã
å®å®çã¡ãœããã¯ããã¬ã€ãå®çŸ©ã®äžéšã§ãã
å®éšçã¡ãœããã¯ãããå¶çŽã®å°ãªãå®å®æ§ããªã·ãŒãæã€å¥ã®ã©ã€ãã©ãªã§ å®çŸ©ãããæ¡åŒµãã¬ã€ããéããŠæäŸãããŸãããã®åŸãäžéšã®ãŠãŒãã£ãªã㣠ã¡ãœããã¯ãæçšæ§ãå®èšŒãããèšèšãæŽç·Žããããšãã³ã¢ã®ãã¬ã€ãå®çŸ©ãžãš ãææ ŒããããŸãã
-
æ¡åŒµãã¬ã€ãã¯ãdyn äºæã§ãªããã¬ã€ã ã 2 ã€ã«åå²ããããã«ã 䜿ããŸãïŒ
- dyn äºæãªã³ã¢ãdyn äºææ§ã®èŠä»¶ãæºããã¡ãœããã ãã« å¶éãããŸãã
- æ¡åŒµãã¬ã€ããdyn äºæã§ãªãæ®ãã®ã¡ãœããïŒããšãã°ã ãžã§ããªãã¯ãªãã©ã¡ãŒã¿ãæã€ã¡ãœããïŒãå«ã¿ãŸãã
-
ã³ã¢ãã¬ã€ããå®è£ ããå ·è±¡åã¯ãæ¡åŒµãã¬ã€ãã«å¯Ÿãããã©ã³ã±ããå®è£ ã® ãããã§ããã¹ãŠã®ã¡ãœãããåŒã³åºããŸãããã¬ã€ããªããžã§ã¯ã ïŒ
dyn CoreTraitïŒã¯ãã³ã¢ãã¬ã€ãäžã®ãã¹ãŠã®ã¡ãœããã«å ããŠãSelf: Sizedãå¿ èŠãšããªãæ¡åŒµãã¬ã€ãäžã®ã¡ãœãããåŒã³åºããŸãã
æ¡åŒµãã¬ã€ããå®çŸ©ãã¹ãã§ããããïŒ
ã©ã®ãããªå Žé¢ã§ãããªãŒé¢æ°ãããæ¡åŒµãã¬ã€ããåªå ãã¹ãã§ããããïŒ
// èäœæš© 2025 Google LLC // SPDX-License-Identifier: Apache-2.0 pub trait StrExt { fn is_palindrome(&self) -> bool; } impl StrExt for &str { fn is_palindrome(&self) -> bool { self.chars().eq(self.chars().rev()) } } // æ¯èŒ fn is_palindrome(s: &str) -> bool { s.chars().eq(s.chars().rev()) }
æ¡åŒµãã¬ã€ãã®äž»ãªå©ç¹ã¯ãèŠã€ããããã§ãã
-
èŠã€ãããã: æ¡åŒµã¡ãœããã¯ãããªãŒé¢æ°ãããèŠã€ãããã ãªããŸããèšèªãµãŒããŒïŒäŸ:
rust-analyzerïŒã¯ãå€éšåã®ã€ã³ã¹ã¿ã³ã¹ã®åŸã«.ãå ¥åãããšãããããåè£ãšããŠæç€ºããŸãã -
ã¡ãœãããã§ãŒã³: æ¡åŒµãã¬ã€ãã®å€§ããªäœ¿ãåæã®åäžãšããŠãã¡ãœãã ãã§ãŒã³ããããŸããããã¯
Iteratorãã¬ã€ãã®åºç€ã§ãããdata.iter().filter(...).map(...)ã®ãããªæµãããããªåŒã³åºããå¯èœã«ããŸãã ãããããªãŒé¢æ°ã§å®çŸããããšãããšãã¯ããã«ç ©éã«ãªããŸã (map(filter(iter(data), ...), ...))ã -
ãžã§ããªã¯ã¹ãš
dyn: ãã¬ã€ãã¯ããžã§ããªã¯ã¹ã®ãã¬ã€ãå¢çãšã㊠䜿ã£ãããdyn Traitã®äžéšãšããŠäœ¿ã£ããã§ããŸãããããªãŒé¢æ°ã¯å¿ ããã ãžã§ããªãã¯ãªæèã§äœ¿ãããšã¯éããŸããã -
API ã®äžäœæ§: æ¡åŒµãã¬ã€ãã¯ããŸãšãŸãã®ãã API ãäœãã®ã«åœ¹ç«ã¡ãŸãã å€éšåã«å¯ŸããŠè€æ°ã®é¢é£é¢æ°ïŒäŸ:
is_palindrome,word_count,to_kebab_caseïŒãããå Žåããããã 1 ã€ã®StrExtãã¬ã€ãã« ãŸãšããæ¹ãããŠãŒã¶ãŒãã€ã³ããŒãããè€æ°ã®ããªãŒé¢æ°ãçšæããããã ãã£ããããŠããããšããããããŸãã -
ãã¬ãŒããªã: ããããå©ç¹ãããäžæ¹ã§ãåçŽãªé¢æ°ã 1 ã€ã ãã®å Žåã«ã¯ã å°çšã®æ¡åŒµãã¬ã€ãã¯ãããããããããŸãããã©ã¡ãã®ã¢ãããŒãã§ã远å ã® ã€ã³ããŒããå¿ èŠã§ãããèŠæ £ããã¡ãœããæ§æãšããå©ç¹ããå®å šãªãã¬ã€ãå®çŸ©ã® ããã®å®åã³ãŒãã«èŠåããªãããšããããŸãã
Typestateãã¿ãŒã³: åé¡
ããå€ã«å¯ŸããŠããã®çŸåšã®ç¶æ ã«å¿ããæå¹ãªæäœã ããèš±å¯ããã«ã¯ãã©ãããã°ããã§ããããïŒ
// Copyright 2025 Google LLC // SPDX-License-Identifier: Apache-2.0 use std::fmt::Write as _; #[derive(Default)] struct Serializer { output: String, } impl Serializer { fn serialize_struct_start(&mut self, name: &str) { let _ = writeln!(&mut self.output, "{name} {{"); } fn serialize_struct_field(&mut self, key: &str, value: &str) { let _ = writeln!(&mut self.output, " {key}={value};"); } fn serialize_struct_end(&mut self) { self.output.push_str("}\n"); } fn finish(self) -> String { self.output } } fn main() { let mut serializer = Serializer::default(); serializer.serialize_struct_start("User"); serializer.serialize_struct_field("id", "42"); serializer.serialize_struct_field("name", "Alice"); // serializer.serialize_struct_end(); // â ããŸã£ããå¿ããŠãã println!("{}", serializer.finish()); }
-
ãã®
Serializerã¯ãæ§é åãããå€ãæžãåºãããšãç®çãšããŠããŸãã -
ãããããã®äŸã§ã¯
finish()ã®åã«serialize_struct_end()ãåŒã¶ã®ãå¿ããŠããŸãããã®çµæãã·ãªã¢ã©ã€ãºãããåºåã¯äžå®å šã«ãªã£ãããæ§æçã«äžæ£ã«ãªã£ããããŸãã -
ãããä¿®æ£ãã 1 ã€ã®æ¹æ³ã¯ãå éšç¶æ ãæåã§è¿œè·¡ããçŸåšã®ç¶æ ãäžæ£ã§ããã°
serialize_struct_field()ãfinish()ã®ãããªã¡ãœããããResultãè¿ãããšã§ãã -
ããããããã«ã¯æ¬ ç¹ããããŸã:
-
å®è£ è ã«ãšã£ãŠééããããæ¹æ³ã§ããRust ã®åã·ã¹ãã ã¯ãç¶æ é·ç§»ã®æ£ããã匷å¶ããå©ãã«ãªããŸããã
-
ãŸããå®è¡æã§ã¯ãªããœãŒã¹ã³ãŒãäžã§èª€çšãããŠããæäœã«å¯ŸããŠãŸã§ããŠãŒã¶ãŒã
Resultå€ãåŠçããªããã°ãªãããäžèŠãªè² æ ãå¢ããŸãã
-
-
ãããã解決çã¯ãæå¹ãªç¶æ é·ç§»ãåã·ã¹ãã å ã«çŽæ¥ã¢ãã«åããããšã§ãã
次ã®ã¹ã©ã€ãã§ã¯ãtypestateãã¿ãŒã³ ãé©çšããŠã³ã³ãã€ã«æã«æ£ããäœ¿çšæ³ã匷å¶ããäºææ§ã®ãªãã¡ãœãããåŒã³åºããããå¿ èŠãªæäœããå¿ãããããããšãäžå¯èœã«ããŸãã
Typestate ãã¿ãŒã³: äŸ
typestate ãã¿ãŒã³ã¯ãå€ã®å®è¡æç¶æ ã®äžéšããã®åã«ãšã³ã³ãŒããããã®ã§ãã ããã«ãããç¡å¹ãŸãã¯é©çšã§ããªãæäœãã³ã³ãã€ã«æã«é²ãããšãã§ããŸãã
// èäœæš© 2025 Google LLC // SPDX-License-Identifier: Apache-2.0 use std::fmt::Write as _; #[derive(Default)] struct Serializer { output: String, } struct SerializeStruct { serializer: Serializer, } impl Serializer { fn serialize_struct(mut self, name: &str) -> SerializeStruct { writeln!(&mut self.output, "{name} {{").unwrap(); SerializeStruct { serializer: self } } fn finish(self) -> String { self.output } } impl SerializeStruct { fn serialize_field(mut self, key: &str, value: &str) -> Self { writeln!(&mut self.serializer.output, " {key}={value};").unwrap(); self } fn finish_struct(mut self) -> Serializer { self.serializer.output.push_str("}\n"); self.serializer } } fn main() { let serializer = Serializer::default() .serialize_struct("User") .serialize_field("id", "42") .serialize_field("name", "Alice") .finish_struct(); println!("{}", serializer.finish()); }
Serializer ã®äœ¿çšãããŒãã£ãŒã:
-
ãã®äŸã¯ Serde ã®
Serializertrait ã«çæ³ãåŸãŠããŸãã Serde ã¯ã·ãªã¢ã©ã€ãºã劥åœãªæ§é ã«åŸãããšãä¿èšŒããããã«ãå éšã§ typestate ã䜿çšããŠããŸãã 詳ããã¯æ¬¡ãåç §ããŠãã ãã: https://serde.rs/impl-serializer.html -
typestate ã®èåŸã«ããéèŠãªèãæ¹ã¯ãç¶æ é·ç§»ãå€ãæ¶è²»ããŠæ°ããå€ãçæããããšã§èµ·ããããšããããšã§ãã åã¹ãããã§ã¯ããã®ç¶æ ã«å¯ŸããŠæå¹ãªæäœã ããå©çšã§ããŸãã
-
ãã®äŸã§ã¯:
-
Serializerããéå§ããããã¯æ§é äœã®ã·ãªã¢ã©ã€ãºãéå§ããããšã ããèš±å¯ããŸãã -
.serialize_struct(...)ãåŒã³åºããšãæææš©ã¯SerializeStructã®å€ãžç§»åããŸãã ãã®æç¹ããã¯ãæ§é äœãã£ãŒã«ãã®ã·ãªã¢ã©ã€ãºã«é¢é£ããã¡ãœããããåŒã³åºããŸããã -
å ã®
Serializerã«ã¯ããã¢ã¯ã»ã¹ã§ããŸãããããã«ãããã¢ãŒãã®æ··åš ïŒããšãã°ãæ§é äœ ã®éäžã§å¥ã® æ§é äœ ãéå§ããããšïŒããfinish()ãæ©ãããã¿ã€ãã³ã°ã§åŒã³åºãããšãé²ããŸãã -
.finish_struct()ãåŒã³åºããåŸã«ã®ã¿ãSerializerãåãåããŸãã ãã®æç¹ã§ãåºåã確å®ãããåå©çšãããã§ããŸãã
-
-
finish_struct()ã®åŒã³åºããå¿ããŠSerializeStructãæ©ãã«ãããããããšãSerializerãäžç·ã«ãããããããŸãã ããã«ãããäžå®å šãªåºåãã·ã¹ãã ã«æŒãåºãããšãé²ããŸãã -
å¯Ÿç §çã«ãåã®ã¹ã©ã€ãã§èŠãããã«ããã¹ãŠã
Serializerã«çŽæ¥å®è£ ããŠããå Žåã¯ã 誰ããéèŠãªæé ãé£ã°ããããã·ãªã¢ã©ã€ãºã®ãããŒãæ··åšããããããããšãé²ããã®ã¯äœããããŸããã
åçŽãª Typestate ãè¶ ããŠ
å¯èœãªç¶æ ãé·ç§»ãæ°å€ãããããŸããŸãè€éãªæ§æãããŒããäºææ§ã®ãªãæäœãé²ãã€ã€ã©ã®ããã«ç®¡çããã°ããã§ããããïŒ
// Copyright 2025 Google LLC // SPDX-License-Identifier: Apache-2.0 struct Serializer {/* [...] */} struct SerializeStruct {/* [...] */} struct SerializeStructProperty {/* [...] */} struct SerializeList {/* [...] */} impl Serializer { // TODO: å®è£ ãã // // fn serialize_struct(self, name: &str) -> SerializeStruct // fn finish(self) -> String } impl SerializeStruct { // TODO: å®è£ ãã // // fn serialize_property(mut self, name: &str) -> SerializeStructProperty // TODO: // ãã®æ§é äœã¯ã©ã®ããã«å®äºãã¹ãã§ããããïŒ ããã¯ããã®æ§é äœãã©ãã«çŸãããã«ãã£ãŠç°ãªããŸã: // - ã«ãŒãã¬ãã«: `Serializer` ãè¿ã // - å¥ã®æ§é äœå ã®ããããã£ãšããŠ: `SerializeStruct` ãè¿ã // - ãªã¹ãå ã®å€ãšããŠ: `SerializeList` ãè¿ã // // fn finish(self) -> ??? } impl SerializeStructProperty { // TODO: å®è£ ãã // // fn serialize_string(self, value: &str) -> SerializeStruct // fn serialize_struct(self, name: &str) -> SerializeStruct // fn serialize_list(self) -> SerializeList // fn finish(self) -> SerializeStruct } impl SerializeList { // TODO: å®è£ ãã // // fn serialize_string(mut self, value: &str) -> Self // fn serialize_struct(mut self, value: &str) -> SerializeStruct // fn serialize_list(mut self) -> SerializeList // TODO: // `SerializeStruct::finish` ãšåæ§ã«ãæ»ãå€ã®åã¯ãã¹ãã«äŸåããŸãã // // fn finish(mut self) -> ??? }
æå¹ãªé·ç§»ã®å³:
-
ãããŸã§ã®ã·ãªã¢ã©ã€ã¶ãŒãåå°ãšããŠãä»åºŠã¯ ãã¹ãããæ§é äœ ãš ãªã¹ã ããµããŒãããããšèããŸãã
-
ããããããã«ãã£ãŠ éè€ ãš æ§é çãªè€éã ã®äž¡æ¹ãçããŸãã
-
ããã«é倧ãªã®ã¯ãããã§ åã·ã¹ãã ã®å¶çŽ ã«çªãåœããããšã§ãããã¹ãã®ã³ã³ããã¹ãããšïŒäŸ: ã«ãŒããæ§é äœããªã¹ãïŒã«ããªã¢ã³ããè€è£œããªãéãã
finish()ãäœãè¿ãã¹ããããã£ãã衚çŸã§ããŸããã -
æå¹ãªé·ç§»ã®å³ãããæ¬¡ã®ããšãåãããŸã:
- é·ç§»ã¯ååž°çã§ãã
- æ»ãå€ã®åã¯ããµãæ§é ããªã¹ãã ã©ãã« çŸãããã«äŸåãã
- åã³ã³ããã¹ãã¯èŠªãžæ»ãããã®çµè·¯ãå¿ èŠãšãã
-
å ·äœåã ãã§ã¯ãããã¯ç®¡çäžèœã«ãªããŸããçŸåšã®ã¢ãããŒãã§ã¯ãåãççºçã«å¢ããæåã§ã€ãªã蟌ãäœæ¥ãå¿ èŠã«ãªããŸãã
-
次ã®ç« ã§ã¯ããžã§ããªã¯ã¹ ã«ãã£ãŠãã³ã³ãã€ã«æã«æå¹ãªæäœã匷å¶ãã€ã€ãããå°ãªããã€ã©ãŒãã¬ãŒãã§ååž°çãªãããŒãã¢ãã«åã§ããããšãèŠãŠãããŸãã
ãžã§ããªã¯ã¹ã䜿ã£ã Typestate ãã¿ãŒã³
typestate ã¢ããªã³ã°ããžã§ããªã¯ã¹ãšçµã¿åãããããšã§ãããžãã¯ãéè€ãããããšãªããããå¹ åºãæå¹ãªç¶æ ãšé·ç§»ã衚çŸã§ããŸãããã®ã¢ãããŒãã¯ãç¶æ æ°ãå¢ããå Žåããè€æ°ã®ç¶æ ãæ¯ãèããå ±æãã€ã€æ§é ãç°ãªãå Žåã«ç¹ã«æçšã§ãã
// èäœæš© 2025 Google LLC // SPDX-License-Identifier: Apache-2.0 struct Serializer<S> { // [...] indent: usize, buffer: String, state: S, } struct Root; struct Struct<S>(S); struct Property<S>(S); struct List<S>(S);
ããã§ãSerializer ãšãã®ç¶æ
åå®çŸ©ã®ã¡ãœãããå®è£
ããããã«å¿
èŠãªèŠçŽ ããã¹ãŠããããŸãããããã«ãããæ¬¡ã®å³ã«ç€ºãããã«ãAPI ã¯æå¹ãªé·ç§»ã®ã¿ãèš±å¯ããããã«ãªããŸãã
-
芪ã³ã³ããã¹ãã远跡ããããã«ãžã§ããªã¯ã¹ã掻çšããããšã§ãstructãlistãproperty ã®åç¶æ éã§æå¹ãªé·ç§»ã匷å¶ãããä»»æã®æ·±ãã«ãã¹ãããã·ãªã¢ã©ã€ã¶ãŒãæ§ç¯ã§ããŸãã
-
ããã«ãããååž°çãªæ§é ãæ§ç¯ãã€ã€ãåç¶æ ã§ã©ã®ã¡ãœããã«ã¢ã¯ã»ã¹ã§ããããå³å¯ã«å¶åŸ¡ã§ããŸãã
-
ãã¹ãŠã®ç¶æ ã«å ±éããã¡ãœããã¯ã
Serializer<S>ã«ãããä»»æã®Sã«å¯ŸããŠå®çŸ©ã§ããŸãã -
ããŒã«ãŒåïŒäŸ:
List<S>ïŒã¯ããŒããµã€ãºåã§ããå¯èœæ§ã®ããããŒã¿ä»¥å€ãå«ãŸãªããããã¡ã¢ãªãå®è¡æã®ãªãŒããŒããããçããŸããããã®å¯äžã®åœ¹å²ã¯ãåã·ã¹ãã ãéããŠæ£ãã API ã®äœ¿ãæ¹ã匷å¶ããããšã§ãã
Serializer: Root ãå®è£ ãã
// Copyright 2025 Google LLC // SPDX-License-Identifier: Apache-2.0 use std::fmt::Write as _; struct Serializer<S> { // [...] indent: usize, buffer: String, state: S, } struct Root; struct Struct<S>(S); impl Serializer<Root> { fn new() -> Self { // [...] Self { indent: 0, buffer: String::new(), state: Root } } fn serialize_struct(mut self, name: &str) -> Serializer<Struct<Root>> { // [...] writeln!(self.buffer, "{name} {{").unwrap(); Serializer { indent: self.indent + 1, buffer: self.buffer, state: Struct(self.state), } } fn finish(self) -> String { // [...] self.buffer } }
å ã®æå¹ãªé·ç§»ã®å³ãæ¯ãè¿ããšãå®è£ ã®åé ã¯æ¬¡ã®ããã«èŠèŠåã§ããŸãã
-
Serializerã®ãrootãã§ã¯ãèš±å¯ãããã®ã¯Structã ãã§ãã -
SerializerãStringã«æçµåã§ããã®ã¯ããã® root ã¬ãã«ããã®ã¿ã§ãã
Serializer: Struct ãå®è£
ãã
// Copyright 2025 Google LLC // SPDX-License-Identifier: Apache-2.0 use std::fmt::Write as _; struct Serializer<S> { // [...] indent: usize, buffer: String, state: S, } struct Struct<S>(S); struct Property<S>(S); impl<S> Serializer<Struct<S>> { fn serialize_property(mut self, name: &str) -> Serializer<Property<Struct<S>>> { // [...] write!(self.buffer, "{}{name}: ", " ".repeat(self.indent * 2)).unwrap(); Serializer { indent: self.indent, buffer: self.buffer, state: Property(self.state), } } fn finish_struct(mut self) -> Serializer<S> { // [...] self.indent -= 1; writeln!(self.buffer, "{}}}", " ".repeat(self.indent * 2)).unwrap(); Serializer { indent: self.indent, buffer: self.buffer, state: self.state.0 } } }
å³ã¯æ¬¡ã®ããã«æ¡åŒµã§ããŸã:
-
Structã¯Propertyããå«ããããŸãã; -
Structãçµäºãããšããã®èŠªã«å¶åŸ¡ãæ»ããŸããåã® ã¹ã©ã€ãã§ã¯ãã®èŠªãRootãšä»®å®ããŠããŸããããå®éã«ã¯ããã¹ããã âstructsâ ã®å Žåã®Structã®ããã«ãå¥ã®ãã®ã«ãªãããšããããŸãã
Serializer: Property ãå®è£ ãã
// Copyright 2025 Google LLC // SPDX-License-Identifier: Apache-2.0 use std::fmt::Write as _; struct Serializer<S> { // [...] indent: usize, buffer: String, state: S, } struct Struct<S>(S); struct Property<S>(S); struct List<S>(S); impl<S> Serializer<Property<Struct<S>>> { fn serialize_struct(mut self, name: &str) -> Serializer<Struct<Struct<S>>> { // [...] writeln!(self.buffer, "{name} {{").unwrap(); Serializer { indent: self.indent + 1, buffer: self.buffer, state: Struct(self.state.0), } } fn serialize_list(mut self) -> Serializer<List<Struct<S>>> { // [...] writeln!(self.buffer, "[").unwrap(); Serializer { indent: self.indent + 1, buffer: self.buffer, state: List(self.state.0), } } fn serialize_string(mut self, value: &str) -> Serializer<Struct<S>> { // [...] writeln!(self.buffer, "{value},").unwrap(); Serializer { indent: self.indent, buffer: self.buffer, state: self.state.0 } } }
Property ç¶æ ã®ã¡ãœããã远å ãããããšã§ãå³ã¯ã»ãŒå®æã§ã:
-
ããããã£ã¯
StringãStruct<S>ããŸãã¯List<S>ãšããŠå®çŸ©ã§ããããããã¹ãããæ§é ã衚çŸã§ããŸãã -
ããã§æ®µéçãªå®è£ ã¯å®äºã§ãã
List<S>ã®ãµããŒããå«ãå®å šãªå®è£ ã¯ã次ã®ã¹ã©ã€ãã§ç€ºããŸãã
Serializer: å®å šãªå®è£
æåã«ç®æããŠãããããŒãæ¯ãè¿ããšã次ã®ããã«ãªããŸãã
ããããã·ãªã¢ã©ã€ã¶ãŒã®åã«çŽæ¥åæ ãããŠããããšãããããŸãã
Serializer ãšãã®ãã¹ãŠã®ç¶æ
ã®å®å
šãªå®è£
ã³ãŒãã¯ããã® Rust playground ã§ç¢ºèªã§ããŸãã
-
ãã®ãã¿ãŒã³ã¯éã®åŒŸäžžã§ã¯ãããŸãããæ¬¡ã®ãããªåé¡ã¯äŸç¶ãšããŠèš±ããŠããŸããŸãã
- 空ãŸãã¯ç¡å¹ãªããããã£åïŒãã㯠newtype ãã¿ãŒã³ ã䜿ã£ãŠä¿®æ£ã§ããŸãïŒ
- éè€ããããããã£åïŒããã¯
Struct<S>ã§è¿œè·¡ããResultã§åŠçã§ããŸãïŒ
-
æ€èšŒã®å€±æãçºçããå Žåã¯ãã¡ãœããã·ã°ããã£ã倿ŽããŠ
Resultãè¿ãããã«ããå埩ãå¯èœã«ããããšãã§ããŸãã#![allow(unused)] fn main() { // Copyright 2025 Google LLC // SPDX-License-Identifier: Apache-2.0 struct PropertySerializeError<S> { kind: PropertyError, serializer: Serializer<Struct<S>>, } impl<S> Serializer<Struct<S>> { fn serialize_property( self, name: &str, ) -> Result<Serializer<Property<Struct<S>>>, PropertySerializeError<S>> { /* ... */ } } } -
ãã® API ã¯åŒ·åã§ãããåžžã«äœ¿ãããããšã¯éããŸãããæ¬çªç°å¢ã®ã·ãªã¢ã©ã€ã¶ãŒã§ã¯ãéåžžã¯ããã·ã³ãã«ãª API ã奜ãŸããtypestate ãã¿ãŒã³ã¯éèŠãªäžå€æ¡ä»¶ã匷å¶ããããã«ã®ã¿äœ¿ãããŸãã
-
çŸå®ã®åªããäŸã® 1 ã€ã
rustls::ClientConfigã§ãããã¯ãžã§ããªã¯ã¹ãš typestate ã䜿ã£ãŠããŠãŒã¶ãŒãå®å šã§æ£ããèšå®æé ãžå°ããŸãã
åçšãã§ãã«ãŒã䜿ã£ãŠäžå€æ¡ä»¶ã匷å¶ãã
åçšãã§ãã«ãŒã¯ãã¡ã¢ãªã®æææš©ã匷å¶ããããã«è¿œå ããããã®ã§ãããä»ã®åé¡ãã¢ãã«åããAPI ã®èª€çšãé²ãããšãã§ããŸãã
// Copyright 2025 Google LLC // SPDX-License-Identifier: Apache-2.0 /// ãã¢ã¯éããŠãããéããŠãããã®ã©ã¡ããã§ãæœé ãŸãã¯è§£é ããã«ã¯æ£ããéµãå¿ èŠã§ãã /// ãã㯠Shared ãªéµãš Owned ãªãã¢ã§ã¢ãã«åãããŠããŸãã pub struct DoorKey { pub key_shape: u32, } pub struct LockedDoor { lock_shape: u32, } pub struct OpenDoor { lock_shape: u32, } fn open_door(key: &DoorKey, door: LockedDoor) -> Result<OpenDoor, LockedDoor> { if door.lock_shape == key.key_shape { Ok(OpenDoor { lock_shape: door.lock_shape }) } else { Err(door) } } fn close_door(key: &DoorKey, door: OpenDoor) -> Result<LockedDoor, OpenDoor> { if door.lock_shape == key.key_shape { Ok(LockedDoor { lock_shape: door.lock_shape }) } else { Err(door) } } fn main() { let key = DoorKey { key_shape: 7 }; let closed_door = LockedDoor { lock_shape: 7 }; let opened_door = open_door(&key, closed_door); if let Ok(opened_door) = opened_door { println!("éµã®åœ¢ç¶ '{}' ã§ãã¢ãéããŸãã", key.key_shape); } else { eprintln!( "ãã¢ã¯éããŸããã§ããïŒããªãã®éµã§éããããã®ã¯åœ¢ç¶ '{}' ã®é åã ãã§ã", key.key_shape ); } }
-
åçšãã§ãã«ãŒãã¡ã¢ãªå®å šæ§ã®ãã°ïŒè§£æŸåŸã®äœ¿çšãããŒã¿ç«¶åïŒãé²ãã®ã¯ããã§ã«èŠãŠããŸããã
-
åã䜿ã£ãŠ API ã圢äœããå¶éããæ¹æ³ãã Typestate ãã¿ãŒã³ ã§ãã§ã«äœ¿ã£ãŠããŸãã
-
èšèªæ©èœã¯ããã°ãã°ç¹å®ã®ç®çã®ããã«å°å ¥ãããŸãã
æéãçµã€ã«ã€ããŠããŠãŒã¶ãŒã¯ãå°å ¥æã«ã¯äºæ³ãããŠããªãã£ãæ¹æ³ã§ãã®æ©èœã䜿ãããæ¹ãçã¿åºãããšããããŸãã
Java 5 㯠2004 幎㫠Generics ãå°å ¥ããŸããããã® äž»ãªå ¬ç§°ç®çã¯åå®å šãªã³ã¬ã¯ã·ã§ã³ãå¯èœã«ããããš ã§ããã
åœåãæ¡çšã¯ãã£ããã§ããããäžéšã®æ°ãããããžã§ã¯ãã§ã¯æåãããžã§ããªã¯ã¹ãäžå¿ã« API ãèšèšãå§ããŸããã
ãã以æ¥ããŠãŒã¶ãŒãšèšèªéçºè ã¯ããžã§ããªã¯ã¹ã®çšéãåå®å šãª API èšèšã®ä»ã®é åãžãšåºããŠããŸããã
- ã¯ã©ã¹æ
å ±ã¯ãJava ã®
Class<T>ã Guava ã®TypeToken<T>ãéããŠä¿æã§ããŸãã - Builder ãã¿ãŒã³ã¯ãååž°çãžã§ããªã¯ã¹ã䜿ã£ãŠå®è£ ã§ããŸãã ããã§ç®æãã®ã䌌ããããªããšã§ããåçšãã§ãã«ãŒã¯è§£æŸåŸã®äœ¿çšãããŒã¿ç«¶åãé²ãããã«å°å ¥ãããŸããããããã§ã¯ããã API èšèšã®ããã®å¥ã®ããŒã«ã® 1 ã€ãšããŠæ±ããŸãã ããã¯ãã¡ã¢ãªå®å šæ§ã®ãã°ãé²ãããšãšã¯é¢ä¿ã®ãªãããã°ã©ã ã®æ§è³ªãã¢ãã«åããããã«ã䜿ããŸãã
- ã¯ã©ã¹æ
å ±ã¯ãJava ã®
-
åçšãã§ãã«ãŒãåé¡è§£æ±ºã®ããŒã«ãšããŠäœ¿ãã«ã¯ããã®æ¬æ¥ã®ç®çããè§£æŸåŸã®äœ¿çšãããŒã¿ç«¶åãé²ãæèã§å¯å€ãšã€ãªã¢ã¹ã鲿¢ããããšã ãšããç¹ãããã£ãããå¿ãããå¿ èŠããããŸãã
ã«ãŒã«ã¯åãã§ãæå³ãå°ãç°ãªãç¶æ³ã®äžã§äœæ¥ããŠãããšèããã¹ãã§ãã
-
ãã®äŸã§ã¯ãæææš©ãšåçšã䜿ã£ãŠç©ççãªãã¢ã®ç¶æ ãã¢ãã«åããŸãã
open_doorã¯LockedDoorã æ¶è²» ããæ°ããOpenDoorãè¿ããŸããå€ãLockedDoorã®å€ã¯ãã䜿ããŸãããééã£ãéµã䜿ãããå Žåããã¢ã¯æœé ããããŸãŸã§ãããã®å Žåã
Resultã®ErrãšããŠè¿ãããŸãããã§ã«éãããã¢ã䜿ãããšãããšãã³ã³ãã€ã«æãšã©ãŒã«ãªããŸãã
-
åæ§ã«ã
lock_doorã¯OpenDoorãæ¶è²»ããããããã¢ã 2 åéããããšãã³ã³ãã€ã«æã«é²ããŸãã -
åçšãã§ãã«ãŒã®ã«ãŒã«ã¯ã¡ã¢ãªå®å šæ§ã®ãã°ãé²ãããã«ååšããŸããããã®æ ¹åºã«ããè«çã·ã¹ãã ã¯ã¡ã¢ãªãäœã§ãããããç¥ã£ãŠãããããã§ã¯ãããŸããã
åçšãã§ãã«ãŒãããŠããããšã¯ããŠãŒã¶ãŒãæäœãã©ã®ãããªé åºã§è¡ãããã«ã€ããŠã®ç¹å®ã®ã«ãŒã«éåã匷å¶ããããšã ãã§ãã
ããã¯ã誀çšãã«ããããããã¯èª€çšäžå¯èœãª API ãèšèšããããã«ãåçšãã§ãã«ãŒã®ã«ãŒã«ã掻çšãã 1 ã€ã®äŸã«ãããŸããã
ã©ã€ãã¿ã€ã ãšåçš: æœè±¡çãªã«ãŒã«
// Copyright 2025 Google LLC // SPDX-License-Identifier: Apache-2.0 // ä¿æããŠããäœããçšæããããã®å éšããŒã¿åã pub struct Internal; // ãå€åŽãã®ããŒã¿ã pub struct Data(Internal); fn shared_use(value: &Data) -> &Internal { &value.0 } fn exclusive_use(value: &mut Data) -> &mut Internal { &mut value.0 } fn deny_future_use(value: Data) {} fn demo_exclusive() { let mut value = Data(Internal); let shared = shared_use(&value); // let exclusive = exclusive_use(&mut value); // âðš let shared_again = shared; } fn demo_denied() { let value = Data(Internal); deny_future_use(value); // let shared = shared_use(&value); // âðš } fn main() {}
-
ãã®äŸã¯ãåçšãã§ãã«ãŒã®ã«ãŒã«ãåç §ããåãé¢ãã ã¡ã¢ãªå®å šæ§ä»¥å€ã®æèã«ãããæå³è«çãªæå³ãžãšæãçŽãããã®ã§ãã
äœãã倿ŽãããŠããããã§ããäœããã¹ã¬ããéã§éãããŠããããã§ããããŸããã
-
Rust ã®åçšãã§ãã«ãŒã§ã¯ãå€ããååŸããã 3 ã€ã®ç°ãªãæ¹æ³ãå©çšã§ããŸãã
-
ææå€
Tãå¥ã®ã¹ã³ãŒãã«è¿ãããªãéããã¹ã³ãŒãã®çµäºæã«å€ã¯ç Žæ£ãããŸãã -
å ±æåç §
&Tããšã€ãªã¢ã·ã³ã°ãèš±å¯ããŸãããå ±æåç §ã䜿çšäžã§ããéã¯å¯å€ã¢ã¯ã»ã¹ãçŠæ¢ããŸãã -
å¯å€åç §
&mut Tãããæç¹ã§ 1 ã€ã®å€ã«å¯ŸããŠååšã§ããã®ã¯ 1 ã€ã ãã§ãããå ±æåç §ãäœæããããã«äœ¿çšã§ããŸãã
-
-
åã:
demo颿°å ã®ã³ã¡ã³ãã¢ãŠãããã 2 è¡ã¯ããªãã³ã³ãã€ã«ãšã©ãŒãåŒãèµ·ããã®ã§ãããã?demo_exclusive:exclusiveåç §ãååŸãããããšãsharedå€ãäŸç¶ãšããŠãšã€ãªã¢ã¹ãããŠããããã§ããdemo_denied:&valueããshared_again_againåç §ãååŸããã 1 è¡åã«ãvalueãæ¶è²»ãããŠããããã§ãã -
ãã¹ãŠã®
&Tãš&mut Tã«ã¯ã©ã€ãã¿ã€ã ãããããšãèŠããŠãããŠãã ãããå€ãã®å ŽåããŠãŒã¶ãŒã泚éãä»ãããæèãããããªããŠããã ãã§ããRust ã³ã³ãã€ã©ã§ã¯å€ãã®å Žåã©ã€ãã¿ã€ã ã çç¥ ã§ãããããç§ãã¡ãã©ã€ãã¿ã€ã ãæç€ºããããšã¯ãŸãã§ããåç §: ã©ã€ãã¿ã€ã çç¥
åå䜿çšã®å€
ãšãã«ã¯ã_äžåºŠãã䜿ããªã_å€ã欲ããããšããããŸãããã®éèŠãªäŸã® 1 ã€ããæå·åéã«ããããNonceãã§ãã
// Copyright 2025 Google LLC // SPDX-License-Identifier: Apache-2.0 pub struct Key(/* 詳现ã¯çç¥ */); /// æå·çšéã«é©ããåå䜿çšã®æ°å€ã pub struct Nonce(u32); /// æå·åŠçã«å®å šãªä¹±æ°çæé¢æ°ã pub fn new_nonce() -> Nonce { Nonce(4) // å ¬å¹³ãªãµã€ã³ããæ¯ã£ãŠéžã°ããŸãã, https://xkcd.com/221/ } /// nonce ãæ¶è²»ããŸãããkey ã data ã¯æ¶è²»ããŸããã pub fn encrypt(nonce: Nonce, key: &Key, data: &[u8]) {} fn main() { let nonce = new_nonce(); let data_1: [u8; 4] = [1, 2, 3, 4]; let data_2: [u8; 4] = [4, 3, 2, 1]; let key = Key(/* 詳现ã¯çç¥ */); // key ãš data ã¯åå©çšããããã³ããŒãããã§ããŸãããnonce ã¯ã§ããŸããã encrypt(nonce, &key, &data_1); // encrypt(nonce, &key, &data_2); // ð ïžâ }
-
åé¡: å€ãäžåºŠãã䜿ãããªãããšããã©ãããã°ä¿èšŒã§ããã§ããããïŒ
-
åæ©: nonce ã¯ããªãã¬ã€æ»æãé²ãããã«æå·ãããã³ã«ã§äœ¿çšããããã©ã³ãã ã§äžæãªããŒã¿ã§ãã
èæ¯: å®éã«ã¯ã誀ã£ãŠ nonce ãåå©çšããŠããŸã£ãäºäŸããããŸãã æãäžè¬çã«ã¯ããã®çµæãšããŠæå·ãããã³ã«ãå®å šã«ç Žç¶»ãã æ¬æ¥ã®åœ¹å²ãæãããªããªããŸãã
nonce ã®åå©çšã®ããæ¹ãå¯Ÿè±¡ã®æå·æ¹åŒã«ãã£ãŠã¯ãç§å¯éµãŸã§ æ»æè ã«èšç®ãããŠããŸãããšããããŸãã
-
Rust ã«ã¯ãããããäžåºŠäœ¿ã£ãããããäºåºŠãšäœ¿ããªãããšããäžå€æ¡ä»¶ã å®çŸããããã®åãããããææ®µããããŸããå€ã æææš©ãåãåãåŒæ° ãšããŠæž¡ãããšã§ãã
-
泚ç®ç¹:
encrypt颿°ã¯nonceã倿ž¡ãïŒæææš©ãåãåãåŒæ°ïŒã§ åãåããŸãããkeyãšdataã¯åç §ã§åãåããŸãã -
åå䜿çšã®å€ã«å¯Ÿãããã¯ããã¯ã¯æ¬¡ã®ãšããã§ãã
-
ã³ã³ã¹ãã©ã¯ã¿ãŒãéå ¬éã«ããŠãåãå éšå€ãæã€å€ããŠãŒã¶ãŒã 2 å æ§ç¯ã§ããªãããã«ããã
-
äžæã«ä¿ã¡ããããŒã¿ããŠãŒã¶ãŒãè€è£œã§ããªãããã«ã
Clone/Copyãã¬ã€ããåçã®ã¡ãœãããå®è£ ããªãã -
å éšã®åãäžéæã«ãïŒnewtype ãã¿ãŒã³ã®ããã«ïŒããŠãŒã¶ãŒãæ¢åã®å€ã èªåã§å€æŽã§ããªãããã«ããã
-
-
åã: ã¹ã©ã€ãã®ã³ãŒãã«ãã newtype ãã¿ãŒã³ã«ã¯ãäœãæ¬ ããŠããã§ããããïŒ
æåŸ ããçã: ã¢ãžã¥ãŒã«å¢çã
宿Œ: ã¢ãžã¥ãŒã«å¢çããªããšããŠãŒã¶ãŒã¯ nonce ãèªåã§æ§ç¯ã§ããŠããŸããŸãã
ä¿®æ£:
KeyãNonceãnew_nonceãã¢ãžã¥ãŒã«ã®å åŽã«çœ®ããŸãã
ããã«æ¢ã
- æå·ã«ãããæ³šæç¹: nonce ã¯ãå®éã®ã©ã³ãã æ§ããªãç䌌乱æ°éçšã§ çæãããå ŽåãäŸç¶ãšã㊠2 å䜿ãããå¯èœæ§ããããŸããããã¯ãã®æ¹æ³ã§ã¯ é²ããŸããããã® API èšèšã¯ 1 ã€ã® nonce ãè€è£œããããšã¯é²ããŸããã ãã¹ãŠã®ããžãã¯ãã°ãé²ãããã§ã¯ãããŸããã
çžäºæä»çãªåç § / ãAliasing XOR Mutabilityã
&T åç
§ãš &mut T åç
§ã®çžäºæä»æ§ãå©çšãããšãæºåãæŽãåã« ããŒã¿ã䜿ãããã®ãé²ããŸãã
// Copyright 2025 Google LLC // SPDX-License-Identifier: Apache-2.0 pub struct QueryResult; pub struct DatabaseConnection {/* ãã£ãŒã«ãã¯çç¥ */} impl DatabaseConnection { pub fn new() -> Self { Self {} } pub fn results(&self) -> &[QueryResult] { &[] // ãããŒã®çµæ } } pub struct Transaction<'a> { connection: &'a mut DatabaseConnection, } impl<'a> Transaction<'a> { pub fn new(connection: &'a mut DatabaseConnection) -> Self { Self { connection } } pub fn query(&mut self, _query: &str) { // ã¯ãšãªãéä¿¡ããããçµæã¯åŸ ããªãã } pub fn commit(self) { // ãã©ã³ã¶ã¯ã·ã§ã³ã®å®è¡ãå®äºããçµæãååŸããã } } fn main() { let mut db = DatabaseConnection::new(); // ãã©ã³ã¶ã¯ã·ã§ã³ `tx` 㯠`db` ãå¯å€åçšããã let mut tx = Transaction::new(&mut db); tx.query("SELECT * FROM users"); // `db` ã¯ãã§ã« `tx` ã«ãã£ãŠå¯å€åçšãããŠãããããããã¯ã³ã³ãã€ã«ãããªãã // let results = db.results(); // âðš // `tx` ã `commit()` ã«ãã£ãŠæ¶è²»ããããšã`db` ã®åçšã¯çµäºããã tx.commit(); // ããã§ `db` ãåã³åçšã§ããã let results = db.results(); }
-
åæ©: ãã®ããŒã¿ããŒã¹ API ã§ã¯ãã¯ãšãªã¯éåæå®è¡ã«åããŠéå§ããã çµæãå©çšå¯èœã«ãªãã®ã¯ãã©ã³ã¶ã¯ã·ã§ã³å šäœãå®äºããŠããã§ãã
ãŠãŒã¶ãŒã¯ã¯ãšãªãå³åº§ã«å®è¡ããããšèããŠãå©çšå¯èœã«ãªãåã«çµæã èªã¿åãããšãããããããŸããããã® API ã®èª€çšã«ãããã¢ããªã äžå®å šãŸãã¯äžæ£ç¢ºãªããŒã¿ãèªã¿åã£ãŠããŸãå¯èœæ§ããããŸãã
äžèŠãããšæãããªèª€è§£ã§ããããã®ãããªç¶æ³ã¯å®éã«èµ·ããããŸãã
åããã: é©åãªäœ¿ãæ¹ã«ã€ããŠããã¥ã¡ã³ããèªãŸãªãã£ãããã«ãAPI ã 誀解ããããšã¯ãããŸããïŒ
æ³å®: ãã£ãªã¢åæã倧åŠåšåŠäžã«ãããã¹ã誀解ã®äŸã
API ã®èŠæš¡ãšãŠãŒã¶ãŒæ°ãå¢ããã«ã€ããŠããã® API ã衚çŸããã·ã¹ãã ã« ã€ããŠæ·±ãç¥èãæã€ãŠãŒã¶ãŒã®å²åã¯å°ãããªããŸãã
-
ãã®äŸã¯ããã®çš®ã®èª€çšãé²ãããã« Aliasing XOR Mutability ãã©ã®ããã« å©çšã§ãããã瀺ããŠããŸãã
-
ããã°ã©ããŒããã¯ãšãªã¯éåæå®è¡ãšããŠéå§ãããã®ã§ã¯ãªãå³åº§ã« å®è¡ããããšèããŠããŸããšããã®ã³ãŒãã¯çµæã®æºåãæŽãåã« èªã¿åã£ãŠããŸãå¯èœæ§ããããŸãã
-
Transactionåã®ã³ã³ã¹ãã©ã¯ã¿ãŒã¯ããŒã¿ããŒã¹æ¥ç¶ãžã®å¯å€åç §ã åãåãããããè¿ãããTransactionå€ã®äžã«ä¿åããŸããããã§æç€ºãããŠããã©ã€ãã¿ã€ã ã«æ°åŸãããå¿ èŠã¯ãªãããã®å Žåã¯åã« ã
Transactionããããããã«æž¡ãããDatabaseConnectionã®ã»ãã é·çããããããšãæå³ããŸãããã®åç §ãå¯å€ãªã®ã¯ãããã«ãã©ã³ã¶ã¯ã·ã§ã³ãéå§ãããçµæã èªã¿åã£ãããããšãã£ãã»ãã®çšéã§
DatabaseConnectionã 䜿ããªãããã«ããããã§ãã -
TransactionãååšããŠããéã¯ããã®Transactionã®äœæå ãšãªã£ãDatabaseConnection倿°ã«ã¯è§ŠããããŸããã宿Œ:
db.results()ã®è¡ãã³ã¡ã³ãè§£é€ããŠãã ããããããããšãdb㯠ãã§ã«å¯å€åçšãããŠãããããã³ã³ãã€ã«ãšã©ãŒã«ãªããŸãã -
泚: ã¯ãšãªçµæãå ¬éãããã²ãã¿ãŒé¢æ°ã®èåŸã«çœ®ãããšã§ã ãã¢ã¯ãã£ããªãã©ã³ã¶ã¯ã·ã§ã³ãååšããªãå Žåã«ã®ã¿ããŠãŒã¶ãŒã¯ ã¯ãšãªçµæã確èªã§ããããšããäžå€æ¡ä»¶ã匷å¶ã§ããŸãã
ã¯ãšãªçµæãæ§é äœã®å ¬éãã£ãŒã«ãã«çœ®ãããŠããå Žåããã®äžå€æ¡ä»¶ã¯ ç Žããããã§ãããã
PhantomData 1/4: åãããŒã¿ãšã»ãã³ãã£ã¯ã¹ã®éè€ããªãã
newtype ãã¿ãŒã³ã¯ããšãã« DRY ååã«åããããšããããŸãããããã©ã解決ããã°ããã§ããããïŒ
// Copyright 2025 Google LLC // SPDX-License-Identifier: Apache-2.0 pub struct UserId(u64); impl ChatUser for UserId { /* ... */ } pub struct PatronId(u64); impl ChatUser for PatronId { /* ... */ } pub struct ModeratorId(u64); impl ChatUser for ModeratorId { /* ... */ } impl ChatModerator for ModeratorId { /* ... */ } pub struct AdminId(u64); impl ChatUser for AdminId { /* ... */ } impl ChatModerator for AdminId { /* ... */ } impl ChatAdmin for AdminId { /* ... */ } // 以äžåæ§ ... fn main() {}
-
åé¡: æš©éãåºå¥ããããã« newtype ãã¿ãŒã³ã䜿ãããã®ã§ãããåãããŒã¿ã«å¯ŸããŠåããã¬ã€ããäœåºŠãå®è£ ããªããã°ãªããŸããã
-
åã: ããã§ã®åå®è£ ã®è©³çްãåããšã«åãã ãšä»®å®ãããšãç¹°ãè¿ããé¿ããã«ã¯ã©ã®ãããªæ¹æ³ãããã§ããããïŒ
æåŸ ããåç:
- ãããå¥ã ã®ããŒã¿åã§ã¯ãªã enum ã«ããã
- ãŠãŒã¶ãŒ ID ãã
struct Admin(u64, UserPermission, ModeratorPermission, AdminPermission);ã®ãããªæš©éããŒã¯ã³ãšã²ãšãŸãšãã«ããã - æš©éããšã³ã³ãŒãããåãã©ã¡ãŒã¿ã远å ããã
- å
åãããŠ
PhantomDataã«èšåããïŒã¿ã€ãã«ã«ãããŸãïŒã
PhantomData 2/4: åã¬ãã«ã®ã¿ã°ä»ã
åãã©ã¡ãŒã¿ã远å ããŠãåã®ã¹ã©ã€ãã®åé¡ã解決ããŸãããã
// Copyright 2025 Google LLC // SPDX-License-Identifier: Apache-2.0 // use std::marker::PhantomData; pub struct ChatId<T> { id: u64, tag: T } pub struct UserTag; pub struct AdminTag; pub trait ChatUser {/* ... */} pub trait ChatAdmin {/* ... */} impl ChatUser for UserTag {/* ... */} impl ChatUser for AdminTag {/* ... */} // 管çè ã¯ãŠãŒã¶ãŒã§ã impl ChatAdmin for AdminTag {/* ... */} // impl <T> Debug for UserTag<T> {/* ... */} // impl <T> PartialEq for UserTag<T> {/* ... */} // impl <T> Eq for UserTag<T> {/* ... */} // 以äžåæ§ ... impl <T: ChatUser> ChatId<T> {/* ãŠãŒã¶ãŒä»¥äžã®ãã¹ãŠã®æ©èœ */} impl <T: ChatAdmin> ChatId<T> {/* 管çè å°çšã®ãã¹ãŠã®æ©èœ */} fn main() {}
-
ããã§ã¯åãã©ã¡ãŒã¿ã䜿ããç°ãªãæš©éãã¬ã€ããå®è£ ãããã¿ã°ãåã«ãã£ãŠæš©éãå¶åŸ¡ããŠããŸãã
ã¿ã°åããããã¯ããŒã«ãŒåã¯ãå©çšè ã API èšèšè ã«ãšã£ãŠäœããã®æå³ãæã€ãŒããµã€ãºåã§ãã
-
åã: ããããã®åã®å®éã®ã€ã³ã¹ã¿ã³ã¹ã«ãããšãã©ã®ãããªåé¡ãçããŸããïŒ
çã: ããããŒããµã€ãºåïŒ
()ãstruct MyTag;ãªã©ïŒã§ãªãå Žåãç§ãã¡ãå¿ èŠãšããŠããã®ã¯ã³ã³ãã€ã«æã«ã®ã¿é¢ä¿ããåæ å ±ã ããªã®ã«ãå¿ èŠä»¥äžã®ã¡ã¢ãªãå²ãåœãŠãããšã«ãªããŸãã -
宿Œ:
tagã®å€ãå®å šã«åé€ããŠãããã³ã³ãã€ã«ããŠã¿ãŸãããïŒããã¯ã³ã³ãã€ã«ã§ããŸãããæªäœ¿çšã®ïŒphantomïŒåãã©ã¡ãŒã¿ãããããã§ãã
ããã§
PhantomDataã®åºçªã§ãïŒ -
宿Œ:
PhantomDataã® import ã®ã³ã¡ã³ããå€ããChatId<T>ãæ¬¡ã®ããã«ããŸãã#![allow(unused)] fn main() { // Copyright 2025 Google LLC // SPDX-License-Identifier: Apache-2.0 pub struct ChatId<T> { id: u64, tag: PhantomData<T>, } } -
PhantomData<T>ã¯ãåãã©ã¡ãŒã¿ãæã€ãŒããµã€ãºåã§ããããã®å€ã¯ãä»ã® ZST ãšåæ§ã«let phantom: PhantomData<UserTag> = PhantomData;ã®ããã«ããããã¯PhantomData::default()ã䜿ã£ãŠæ§ç¯ã§ããŸãã宿Œ:
ChatId<T>ã«å¯ŸããŠFrom<u64>ãå®è£ ããPhantomDataã®æ§ç¯ã匷調ããŸãã#![allow(unused)] fn main() { // Copyright 2025 Google LLC // SPDX-License-Identifier: Apache-2.0 impl<T> From<u64> for ChatId<T> { fn from(value: u64) -> Self { ChatId { id: value, // ãŸã㯠`PhantomData::default()` tag: PhantomData, } } } } -
PhantomData㯠Typestate ãã¿ãŒã³ã®äžéšãšããŠäœ¿çšã§ããåãæ§é ãæã¡ãªããç°ãªãã¡ãœãããæã€ããŒã¿ã衚çŸã§ããŸããããšãã°ãTaggedData<Start>ã«ã¯ãTaggedData<End>ã«ã¯ãªãã¡ãœããããã¬ã€ãå®è£ ãæãããããšãã§ããŸãã
PhantomData 3/4: å€éšãªãœãŒã¹ã®ã©ã€ãã¿ã€ã
å€éšãªãœãŒã¹ã®äžå€æ¡ä»¶ã¯ãå€ãã®å Žåãã©ã€ãã¿ã€ã èŠåã§è¡šçŸã§ããããšãšäžèŽããŸãã
// Copyright 2025 Google LLC // SPDX-License-Identifier: Apache-2.0 // use std::marker::PhantomData; /// C ã®ããŒã¿ããŒã¹ã©ã€ãã©ãªãžã®çŽæ¥ç㪠FFIã /// ãã® API ã¯ãã®ãŸãŸæäŸããããã®ã§ããããã¡ãããã¯å€æŽã§ããŸããã mod ffi { pub type DatabaseHandle = u8; // åæã«éããããŒã¿ããŒã¹ã¯æå€§ 255 å fn database_open(name: *const std::os::raw::c_char) -> DatabaseHandle { unimplemented!() } // ... ãªã©ã } struct DatabaseConnection(ffi::DatabaseHandle); struct Transaction<'a>(&'a mut DatabaseConnection); impl DatabaseConnection { fn new_transaction(&mut self) -> Transaction<'_> { Transaction(self) } } fn main() {}
-
Aliasing XOR Mutability ã®äŸã«ãã£ã ãã©ã³ã¶ã¯ã·ã§ã³ API ãæãåºããŠãã ããã
ãã©ã³ã¶ã¯ã·ã§ã³ãã¢ã¯ãã£ããªéããŒã¿ããŒã¹ãããã¯ããããã ãã©ã³ã¶ã¯ã·ã§ã³åã®äžã§ããŒã¿ããŒã¹æ¥ç¶ãžã®å¯å€åç §ãä¿æããŠããŸããã
ãã®äŸã§ã¯ãå€éšã®é Rust API ã®äžã«
TransactionAPI ãå®è£ ããããšèããŠããŸãããŸãã
&mut DatabaseConnectionãä¿æããTransactionåãå®çŸ©ãããšããããå§ããŸãã -
質å: ãã®å®è£ ã®éçã¯äœã§ããããã
u8ã¯å®è£ äžæ£ç¢ºã§ããã å€éš API ã䜿ãããã®æ å ±ãšããŠååã§ãããšä»®å®ããŠãã ãããæ³å®:
- 64 ããããã©ãããã©ãŒã ã§ã¯ã鿥åç §ã®ããã«å¿ èŠä»¥äžã« 7 ãã€ãå€ã䜿ãã å®è¡æã«ã¯ãã€ã³ã¿ã®ããªãã¡ã¬ã³ã¹ã®ã³ã¹ããããããŸãã
-
åé¡: ãã©ã³ã¶ã¯ã·ã§ã³ã«ã¯ããããäœæããããŒã¿ããŒã¹æ¥ç¶ãåçšããããäžæ¹ã§ã
Transactionãªããžã§ã¯ãã«ã¯å®éã®åç §ãæ ŒçŽããããããŸããã -
質å: ã©ã€ãã¿ã€ã ãã©ã¡ãŒã¿ãæ®ãããŸãŸã
Transactionããå¯å€åç §ãåãé€ããšã©ããªãã§ãããããæ³å®: æªäœ¿çšã®ã©ã€ãã¿ã€ã ãã©ã¡ãŒã¿ã«ãªããŸãã
-
åã®ã¹ã©ã€ãã®åã¿ã°ä»ããšåæ§ã«ããã®æªäœ¿çšã®ã©ã€ãã¿ã€ã ãã©ã¡ãŒã¿ã 衚ãããã«
PhantomDataã䜿ãããšãã§ããŸããéãã¯ããã®ã©ã€ãã¿ã€ã ãå¥ã®åãšäžç·ã«äœ¿ãå¿ èŠãããããšã§ããã ãã®å¥ã®åèªäœã¯ããã»ã©éèŠã§ã¯ãªããšããç¹ã§ãã
-
宿Œ:
Transactionãæ¬¡ã®ããã«å€æŽããŸãã#![allow(unused)] fn main() { // Copyright 2025 Google LLC // SPDX-License-Identifier: Apache-2.0 struct Transaction<'a> { connection: DatabaseConnection, _phantom: PhantomData<&'a mut DatabaseConnection>, } }DatabaseConnection::new_transaction()ã¡ãœãããæŽæ°ããŸãã#![allow(unused)] fn main() { // Copyright 2025 Google LLC // SPDX-License-Identifier: Apache-2.0 impl DatabaseConnection { fn new_transaction<'a>(&'a mut self) -> Transaction<'a> { Transaction { connection: DatabaseConnection(self.0), _phantom: PhantomData } } } }ããã«ããããããäœæãã
DatabaseConnectionã«çµã³ä»ãããã ææãããããŒã¿ããŒã¹æ¥ç¶ãåŸãããŸãããåç §ãæ ŒçŽããçããã å®è¡æã®ã¡ã¢ãªãããããªã³ããå°ããã§ããŸããPhantomDataã¯ãŒããµã€ãºåïŒ()ãstruct MyZeroSizedType;ã®ãããªãã®ïŒãªã®ã§ãTransactionã®ãµã€ãºã¯ ÑепеÑÑu8ãšåãã«ãªããŸãã代ããã«åç §ãä¿æããŠããå®è£ ã¯ã
usizeãšåã倧ããã§ããã
ããã«æ¢ã
-
åãšå€ã®éã®é¢ä¿ããã®ããã«ãšã³ã³ãŒãããæ¹æ³ã¯ã
unsafeãšçµã¿åããããš éåžžã«åŒ·åã§ãããšããã®ããã©ã€ãã¿ã€ã ãæäœããæ¹æ³ãã»ãšãã©ä»»æã«ãªãããã§ãã ããã¯å±éºã§ããããŸãããå€éšã®æ©æ¢°æ€èšŒæžã¿èšŒæã®ãããªããŒã«ãšçµã¿åãããããšã§ã é¢é£ããããŒã¿åã«ã©ã€ãã¿ã€ã ãšå®å šæ§ã«é¢ããæåŸ ããšã³ã³ãŒããã€ã€ã 埪ç°/èªå·±åç §åãå®å šã«ãšã³ã³ãŒãã§ããŸãã -
GhostCell (2021) ã®è«æãšã ãã®é¢é£å®è£ ã¯ã ãã®çš®ã®åãçµã¿ã瀺ããŠããŸããborrow checker ã«ã¯å¶çŽããããŸããã ããã§ãæãéãäœ¿ãæ¹æ³ã¯ããããã®ããã§ ããããæãéã®äœ¿ãæ¹ã äžè²«ããŠããŠå®å šã§ããããšã瀺ã ããšãã§ããŸãã
PhantomData 4/4: OwnedFd ãš BorrowedFd
BorrowedFd ã¯ãPhantomData ãå®éã«æŽ»çšãããŠãã代衚çãªäŸã§ãã
// Copyright 2025 Google LLC // SPDX-License-Identifier: Apache-2.0 use std::marker::PhantomData; use std::os::raw::c_int; mod libc_ffi { use std::os::raw::{c_char, c_int}; pub unsafe fn open(path: *const c_char, oflag: c_int) -> c_int { 3 } pub unsafe fn close(fd: c_int) {} } struct OwnedFd { fd: c_int, } impl OwnedFd { fn try_from_fd(fd: c_int) -> Option<Self> { if fd < 0 { return None; } Some(OwnedFd { fd }) } fn as_fd<'a>(&'a self) -> BorrowedFd<'a> { BorrowedFd { fd: self.fd, _phantom: PhantomData } } } impl Drop for OwnedFd { fn drop(&mut self) { unsafe { libc_ffi::close(self.fd) }; } } struct BorrowedFd<'a> { fd: c_int, _phantom: PhantomData<&'a ()>, } fn main() { // æžã蟌ã¿å°çšãšäœææš©éãæå®ããçã® syscall ã§ãã¡ã€ã«ãäœæããŸãã let fd = unsafe { libc_ffi::open(c"c_str.txt".as_ptr(), 065) }; // æŽæ°ã®ãã¡ã€ã«ãã£ã¹ã¯ãªãã¿ã®æææš©ã `OwnedFd` ã«æž¡ããŸãã // `OwnedFd::drop()` ã¯ãã¡ã€ã«ãã£ã¹ã¯ãªãã¿ãéããŸãã let owned_fd = OwnedFd::try_from_fd(fd).expect("syscall ã§ãã¡ã€ã«ãéããŸããã§ããïŒ"); // `OwnedFd` ãã `BorrowedFd` ãäœæããŸãã // `BorrowedFd::drop()` ã¯ãã¡ã€ã«ãææããŠããªãããããã¡ã€ã«ãéããŸããïŒ let borrowed_fd: BorrowedFd<'_> = owned_fd.as_fd(); // std::mem::drop(owned_fd); // âðš std::mem::drop(borrowed_fd); let second_borrowed = owned_fd.as_fd(); // owned_fd ã¯ããã§ drop ããããã¡ã€ã«ã¯éããããŸãã }
-
ãã¡ã€ã«ãã£ã¹ã¯ãªãã¿ã¯ãç¹å®ã®ããã»ã¹ã«ãããã¡ã€ã«ãžã®ã¢ã¯ã»ã¹ã衚ããŸãã
è£è¶³: ããã€ã¹ã OS åºæã®æ©èœã¯ãunix ç³»ã·ã¹ãã ã§ã¯ãã¡ã€ã«ã§ãããã®ããã«å ¬éãããŸãã
-
OwnedFdã¯ããã¡ã€ã«ãã£ã¹ã¯ãªãã¿ã®æææš©ãæã€ã©ãããŒåã§ããããã¯ãã¡ã€ã«ãã£ã¹ã¯ãªãã¿ã_ææ_ãã drop ããããšãããéããŸããæ³š: ããã§ã¯ç¬èªå®è£ ã䜿ã£ãŠããã®ã§ãæç€ºçãª
Dropå®è£ ã«æ³šç®ããŠãã ãããBorrowedFdã¯ãã®åçšçã«ãããåã§ãããdrop ãããŠããã¡ã€ã«ãéããå¿ èŠã¯ãããŸãããæ³š:
BorrowedFdã«ã¯Dropãæç€ºçã«å®è£ ããŠããŸããã -
BorrowedFdã¯ãPhantomDataã§æããã©ã€ãã¿ã€ã ã䜿ã£ãŠã ããã®ãã¡ã€ã«ãã£ã¹ã¯ãªãã¿ãååšãããªãããããéãã責任ãè² ã£ãŠããªããŠãã OS ã®ãã¡ã€ã«ãã£ã¹ã¯ãªãã¿ã¯äŸç¶ãšããŠéããŠããããšããäžå€æ¡ä»¶ã匷å¶ããŸããBorrowedFdã®ã©ã€ãã¿ã€ã ãã©ã¡ãŒã¿ã¯ãããã°ã©ã å ã«ããã®ç¹å®ã®BorrowedFdãšåãã ãé·ãçåãããããããã¯ããããé·ãçåããå¥ã®å€ãååšããããšãèŠæ±ããŸã ïŒãã®å Žåã¯OwnedFdã§ãïŒã宿Œ:
std::mem::drop(owned_fd)ã®è¡ãã³ã¡ã³ãè§£é€ããŠã³ã³ãã€ã«ããŠã¿ããšãborrowed_fdãowned_fdã®ã©ã€ãã¿ã€ã ã«äŸåããŠããããšã瀺ããŸãããã㯠API èšèšè ã«ãã£ãŠãããã®å¥ã®å€ããããã¡ã€ã«ãžã®ã¢ã¯ã»ã¹ãéãããŸãŸã«ããŠããã ãšããæå³ã«ãªããã API ã«ãšã³ã³ãŒããããŠããŸãã
Rust ã® borrow checker ã¯ãäžæ¹ã®å€ãããäžæ¹ã®å€ãšå°ãªããšãåãã ãé·ãçåããªããã°ãªããªã ãšãããã®é¢ä¿ã匷å¶ããããããã® API ã®å©çšè ã¯ãæ£ãããã¡ã€ã«ãã£ã¹ã¯ãªãã¿ã®ãšã€ãªã¢ã·ã³ã°ã ã¯ããŒãºã®ããžãã¯ãèªåã§æ±ãå¿ èŠããããŸããã
ããŒã¯ã³å
ãã©ã€ããŒããªã³ã³ã¹ãã©ã¯ã¿ãæã€åã¯ãäžå€æ¡ä»¶ã®èšŒæãšããŠå©çšã§ããŸãã
// Copyright 2025 Google LLC // SPDX-License-Identifier: Apache-2.0 pub mod token { // ã¢ãžã¥ãŒã«å¢çã®å åŽã«ããããã©ã€ããŒããã£ãŒã«ããæã€å ¬éåã pub struct Token { proof: () } pub fn get_token() -> Option<Token> { Some(Token { proof: () }) } } pub fn protected_work(token: token::Token) { println!("We have a token, so we can make assumptions.") } fn main() { if let Some(token) = token::get_token() { // ããŒã¯ã³ãããã®ã§ããã®äœæ¥ãå®è¡ã§ããŸãã protected_work(token); } else { // ããŒã¯ã³ãååŸã§ããªãã£ãã®ã§ã`protected_work` ãåŒã³åºããŸããã } }
-
åæ©: ãŠãŒã¶ãŒãç¹å®ã®ã¿ã¹ã¯ãå®è¡ãããŸã§ãæ©èœãžã®ã¢ã¯ã»ã¹ã å¶éã§ããããã«ãããã
ããã¯ãstruct ãš module ã®ãã©ã€ãã·ãŒã«ãŒã«ãéããŠãAPI ã®å©çšè ã èªåã§ã¯æ§ç¯ã§ããªãåãå®çŸ©ããããšã§å®çŸã§ããŸãã
Newtypes ãåæ§ã®æ¹æ³ã§ãã©ã€ãã·ãŒã«ãŒã«ã䜿ãã å€ãå®è¡æã«äžå€æ¡ä»¶ãæºããããšãä¿èšŒãããªãéããæ§ç¯ã å¶éããŸãã
-
åã: ããã§ã®
proof: ()ãã£ãŒã«ãã®ç®çã¯äœã§ããïŒproof: ()ããªããã°ãTokenã«ã¯ãã©ã€ããŒããã£ãŒã«ãããªããªãã ãŠãŒã¶ãŒã¯Tokenã®å€ãä»»æã«æ§ç¯ã§ããããã«ãªããŸãã宿Œ:
mainã§ããŒã¯ã³ãæåã§æ§ç¯ããŠã¿ãŠãã³ã³ãã€ã«ãšã©ãŒã 瀺ããŠãã ããã宿Œ:Tokenããproofãã£ãŒã«ããåé€ããŠã ãã©ã€ããŒããã£ãŒã«ãããªããã°ãŠãŒã¶ãŒãTokenãæ§ç¯ã§ããããšã瀺ããŠãã ããã -
Tokenåãã¢ãžã¥ãŒã«å¢ç (token) ã®å åŽã«çœ®ãããšã§ããã® ã¢ãžã¥ãŒã«ã®å€åŽã®ãŠãŒã¶ãŒã¯proofãã£ãŒã«ãã«ã¢ã¯ã»ã¹ããæš©éããªãããã èªåã§ãã®å€ãæ§ç¯ã§ããŸãããAPI éçºè ã¯ããããã®ããŒã¯ã³ãçæããã¡ãœããã颿°ãå®çŸ©ã§ããŸãã ãŠãŒã¶ãŒã«ã¯ã§ããŸããã
ãã®ããŒã¯ã³ã¯ãAPI éçºè ããã®ããŒã¯ã³ãžã®ã¢ã¯ã»ã¹ã«å¯ŸããŠå®ããæ¡ä»¶ã æºãããããšã®èšŒæã«ãªããŸãã
-
åã: API éçºè ãããããåé¿ããææ®µã誀ã£ãŠæã¡èŸŒãã§ããŸãã®ã¯ ã©ã®ãããªå Žåã§ããããïŒ
ãã·ãªã¢ã©ã€ãºå®è£ ããã»ãã®ããŒãµãŒ / ãfrom stringãå®è£ ã ãŸãã¯
Defaultã®å®è£ ãšãã£ãçããæåŸ ããŸãã
æš©éããŒã¯ã³
ããŒã¯ã³åã¯ãç¢ºèªæžã¿ã®æš©éã®èšŒæãšããŠããŸãæ©èœããŸãã
// Copyright 2025 Google LLC // SPDX-License-Identifier: Apache-2.0 mod admin { pub struct AdminToken(()); pub fn get_admin(password: &str) -> Option<AdminToken> { if password == "Password123" { Some(AdminToken(())) } else { None } } } // æš©éãããããšã確èªããå¿ èŠã¯ãããŸããã // `AdminToken` åŒæ°ãããã®ãããªç¢ºèªãšåçã ããã§ãã pub fn add_moderator(_: &admin::AdminToken, user: &str) {} fn main() { if let Some(token) = admin::get_admin("Password123") { add_moderator(&token, "CoolUser"); } else { eprintln!("ãã¹ã¯ãŒããæ£ãããããŸãããæš©éã蚌æã§ããŸããã§ããã") } }
-
ãã®äŸã§ã¯ããã¹ã¯ãŒãã«ãã£ãŠãã£ãã ã¯ã©ã€ã¢ã³ãã®ç®¡çè æš©éãååŸãããããã® æš©éãååŸããåŸã«ãŠãŒã¶ãŒãžã¢ãã¬ãŒã¿ãŒæš©éãäžããããšãã¢ãã«åããŠããŸãã
AdminTokenåã¯ãããŠãŒã¶ãŒãæ£ããæš©éãæã£ãŠããããšã®èšŒæããšã㊠æ©èœããŸããã³ãŒãå ã§ãŠãŒã¶ãŒã«ãã¹ã¯ãŒãã®å ¥åãæ±ãããã¹ã¯ãŒããæ£ãããã°ã ç¹å®ã®ç°å¢ïŒããã§ã¯ãã£ããã¯ã©ã€ã¢ã³ãïŒå ã§ç®¡çè ã¢ã¯ã·ã§ã³ãå®è¡ããããã®
AdminTokenãååŸããŸããæš©éãååŸãããã
add_moderator颿°ãåŒã³åºããŸãããã®ããŒã¯ã³åãªãã§ã¯ãã®é¢æ°ãåŒã³åºããªãããã ããããåŒã³åºãããšããããšèªäœãããæš©éãæã£ãŠãããšã¿ãªããŸãã
-
宿Œ:
mainã§ããäžåºŠAdminTokenãæ§ç¯ããããšããŠã¿ãŠãã ãããããã¯ã æçšãªããŒã¯ã³ã®åºç€ããããããä»»æã« æ§ç¯ã§ããªãããã«ããããšã«ãããšæ¹ããŠç€ºãããã§ãã
ããŒã¿ãæã€ããŒã¯ã³å: MutexGuard
ããŒã¯ã³åã远å ã®ããŒã¿ãå¿
èŠãšããããšããããŸããMutexGuard ã¯ã æš©é + ããŒã¿ã衚ãããŒã¯ã³ã®äžäŸã§ãã
// èäœæš© 2025 Google LLC // SPDX-License-Identifier: Apache-2.0 use std::sync::{Arc, Mutex, MutexGuard}; fn main() { let mutex = Arc::new(Mutex::new(42)); let try_mutex_guard: Result<MutexGuard<'_, _>, _> = mutex.lock(); if let Ok(mut guarded) = try_mutex_guard { // ååŸãã MutexGuard ã¯ãæä»çã¢ã¯ã»ã¹ã®èšŒæã§ãã *guarded = 451; } }
-
Mutexã¯ãå€ãžã®èªã¿åã/æžã蟌ã¿ã¢ã¯ã»ã¹ã«å¯ŸããŠçžäºæä»ã匷å¶ããŸãããã§ã« ãã®ã³ãŒã¹ã®ååã§Mutexã¯æ±ããŸãããïŒåç §: RAII/MutexïŒãããã§ã¯ ç¹ã«MutexGuardãèŠãŠãããŸãã -
MutexGuardã¯ãããæç¹ã§èªã¿åã/æžã蟌ã¿ã¢ã¯ã»ã¹æš©ãããããšã蚌æãããMutexã«ãã£ãŠçæãããå€ã§ããMutexGuardã¯ããã«ããããçæããMutexãžã®åç §ãä¿æããŠãããDerefãšDerefMutã®å®è£ ã«ãã£ãŠãåºç€ãšãªãMutexããã®ããŒã¿ã ãŠãŒã¶ãŒããéå ¬éã®ãŸãŸãMutexã®ããŒã¿ã«ã¢ã¯ã»ã¹ã§ããŸãã -
mutex.lock()ãMutexGuardãè¿ããªãå Žåãmutex å ã®å€ã倿Žãã æš©éã¯ãããŸãããæš©éããªãã ãã§ãªãã
MutexGuardãåŸãªãéããmutex ã®ããŒã¿ã«ã¢ã¯ã»ã¹ãã ææ®µããããŸããããã㯠C++ ãšå¯Ÿç §çã§ããC++ ã§ã¯ãmutex ãš lock guard ã¯ããŒã¿èªäœãžã®ã¢ã¯ã»ã¹ã å¶åŸ¡ãããåã«ãããŒã¿ãèªããšããæäœãããšãã«æ¯åãŠãŒã¶ãŒã確èªããããšã èŠããŠãããªããã°ãªããªããã©ã°ãšããŠæ©èœããã ãã§ãã
-
宿Œ:
mutex倿°ãå¯å€ã«ããŠããããããããªãã¡ã¬ã³ã¹ããŠå€ã倿Žããããš ããŠã¿ãŠãã ãããããã«ã¯Derefå®è£ ããªããmutex guard ãååŸãã以å€ã«ã ãããä¿æããŠããããŒã¿ãžå°éããæ¹æ³ããªãããšã瀺ããŠãã ããã
倿°åºæã®ããŒã¯ã³ïŒãã©ã³ãã£ã³ã° 1/4ïŒ
ããŒã¯ã³ãç¹å®ã®å€æ°ã«çµã³ä»ãããå Žåã¯ã©ãããã°ããã§ããããïŒ
// èäœæš© 2025 Google LLC // SPDX-License-Identifier: Apache-2.0 struct Bytes { bytes: Vec<u8>, } struct ProvenIndex(usize); impl Bytes { fn get_index(&self, ix: usize) -> Option<ProvenIndex> { if ix < self.bytes.len() { Some(ProvenIndex(ix)) } else { None } } fn get_proven(&self, token: &ProvenIndex) -> u8 { unsafe { *self.bytes.get_unchecked(token.0) } } } fn main() { let data_1 = Bytes { bytes: vec![0, 1, 2] }; if let Some(token_1) = data_1.get_index(2) { data_1.get_proven(&token_1); // åé¡ãªãåäœããŸãïŒ // let data_2 = Bytes { bytes: vec![0, 1] }; // data_2.get_proven(&token_1); // panic ããŸãïŒ ãããé²ããã§ããããïŒ } }
-
ã³ãŒãå ã®_ç¹å®ã®å€æ°_ã«ããŒã¯ã³ãçµã³ä»ãããå Žåã¯ã©ãã§ããããïŒ Rust ã®å ã·ã¹ãã ã§ãããå®çŸã§ããã§ããããïŒ
-
åæ©: ãã€ãé åã«å¯Ÿãããæ¢ç¥ã§æå¹ãªã€ã³ããã¯ã¹ã衚ãããŒã¯ã³åãæã¡ãã ã®ã§ãã
ãããã®èšŒææžã¿ã€ã³ããã¯ã¹ãããã°ãããŒã¯ã³ã_ååšããã€ã³ããã¯ã¹ã®èšŒæ_ãš ããŠæ©èœãããããå¢çãã§ãã¯ãå®å šã«åé¿ã§ããŸãã
ã€ã³ããã¯ã¹ãæå¹ã§ããããšã¯åãã£ãŠããã®ã§ã
get_proven()ã¯å¢çãã§ã㯠ãçç¥ã§ããŸãã -
ãã®äŸã§ã¯ãããé åã®èšŒææžã¿ã€ã³ããã¯ã¹ãå¥ã®é åã§äœ¿ãããã®ãé²ãä»çµã¿ ããããŸããããã®å Žåã«ã€ã³ããã¯ã¹ãç¯å²å€ã§ããã°ãããã¯æªå®çŸ©åäœã« ãªããŸãã
-
宿Œ:
data_2.get_proven(&token_1);ã®è¡ã®ã³ã¡ã³ãã¢ãŠããå€ããŸããããã§ã³ãŒã㯠panic ããŸãïŒ ã€ã³ããã¯ã¹çšããŒã¯ã³åã«ããããã® ãã¯ãã¹ãªãŒããŒããã³ã³ãã€ã«æã«é²ãããã®ã§ãã
-
åããã: ãããå®çŸããã«ã¯ãã©ã®ãããªæ¹æ³ãèããããã§ããããïŒ
åè¬è ãããããè¯ãå®è£ ã«ãã©ãçããªãããšã¯æ³å®ãããŸãããå®éšãããã ææ¡ã«æ²¿ã£ãŠè©Šãé²ãããããããšã«ã¯ååãã§ããŠãã ããã
-
åããã: ä»£æ¿æ¡ã«ã¯äœãããããªãããã§ã¯ååã§ãªãã®ã§ããããïŒ
ç¹ã«
Vec::getãšBytes::get_indexã®ã©ã¡ãããã§ã«å®è¡æãã§ãã¯ã 䜿ã£ãŠãããããã€ã³ããã¯ã¹å¢çã®å®è¡æãã§ãã¯ãšããæ¡ãåºãŠããã¯ãã§ããå®è¡æã®å¢çãã§ãã¯ã§ã¯ããããããã®èª€ã£ãã¯ãã¹ãªãŒããŒãé²ããã panic ãèµ·ããããšãä¿èšŒãããã ãã§ãã
-
ããã§è¡ããã®çš®ã®ããŒã¯ã³é¢é£ä»ãã¯ããã©ã³ãã£ã³ã°ãšåŒã°ããŸããããã¯ã ããå€ãã® API èšèšã«ããŒã¯ã³åãé©çšã§ããããã«ããé«åºŠãªãã¯ãã㯠ã§ãã
-
GhostCellã¯ãã® ææ³ã®èåãªå©çšäŸã§ãããåŸã®ã¹ã©ã€ãã§è§ŠããŸãã
PhantomData ãšã©ã€ãã¿ã€ã ã®ãµãã¿ã€ãã³ã°ïŒãã©ã³ãã£ã³ã° 2/4ïŒ
ã¢ã€ãã¢:
- åããŒã¯ã³ã«å¯ŸããŠã©ã€ãã¿ã€ã ãäžæã®ãã©ã³ããšããŠäœ¿ãã
- ã©ã€ãã¿ã€ã å士ãæé»ã«çžäºå€æãããªããããååã«åºå¥ã§ããããã«ããã
// Copyright 2025 Google LLC // SPDX-License-Identifier: Apache-2.0 use std::marker::PhantomData; #[derive(Default)] struct InvariantLifetime<'id>(PhantomData<&'id ()>); // äž»ãªãã€ã³ã struct Wrapper<'a> { value: u8, invariant: InvariantLifetime<'a> } fn lifetime_separator<T>(value: u8, f: impl for<'a> FnOnce(Wrapper<'a>) -> T) -> T { f(Wrapper { value, invariant: InvariantLifetime::default() }) } fn try_coerce_lifetimes<'a>(left: Wrapper<'a>, right: Wrapper<'a>) {} fn main() { lifetime_separator(1, |wrapped_1| { lifetime_separator(2, |wrapped_2| { // ããã¯ã³ã³ãã€ã«ãããªãããã«ããã try_coerce_lifetimes(wrapped_1, wrapped_2); }); }); }
-
Rust ã§ã¯ãã©ã€ãã¿ã€ã å士ã«ãµãã¿ã€ãé¢ä¿ãæãç«ã€ããšããããŸãã
ãã®çš®ã®é¢ä¿ã«ãããããã©ã€ãã¿ã€ã ãå¥ã®ã©ã€ãã¿ã€ã ããé·ãåç¶ãããã©ãããã³ã³ãã€ã©ã倿ã§ããŸãã
ããã©ã€ãã¿ã€ã ãå¥ã®ã©ã€ãã¿ã€ã ããé·ãåç¶ãããã倿ã§ãããšããããšã¯ãæãçãå ±éã©ã€ãã¿ã€ã ã¯æåã«çµãããã®ã ãšèšããããšã§ããããŸãã
ããã¯å€ãã®å Žåã«æçšã§ãããšããã®ãã2 ã€ã®ç°ãªãã©ã€ãã¿ã€ã ãéãªã£ãŠããé åã§ã¯ãããããåããã®ãšããŠæ±ããããã§ãã
éåžžãããã¯æãŸããæåã§ãããããããã§ã¯ãã©ã€ãã¿ã€ã ãå€ã®åºå¥ã«äœ¿ãããã®ã§ã宣èšãã倿°ããšã«æ¯å newtype ãäœããªããŠããããŒã¯ã³ã 1 ã€ã®å€æ°ã«ããé©çšãããªãããã«ãããã®ã§ãã
-
ç®æš: Rust ã³ã³ãã€ã©ããäžæ¹ã仿¹ããé·ãåç¶ãããã©ããã倿ã§ããªã 2 ã€ã®ã©ã€ãã¿ã€ã ãã»ããã
ããã§ã¯
try_coerce_lifetimesãã³ã³ãã€ã«æãã§ãã¯ãšããŠäœ¿ããã©ã€ãã¿ã€ã ã«å ±éã®ããçãã©ã€ãã¿ã€ã ãååšãããã©ããïŒã€ãŸããµãã¿ã€ãåããããã©ããïŒãèŠãŠããŸãã -
泚: ãã®ã¹ã©ã€ãã¯çŸæç¹ã§ã¯ã³ã³ãã€ã«ã§ããŸããããã®ã¹ã©ã€ãã®çµãããŸã§ã«ã¯ã
try_coerce_lifetimesãã³ã¡ã³ãã¢ãŠããããšãã«ã®ã¿ã³ã³ãã€ã«ã§ããããã«ãªãã¯ãã§ãã -
ãã®ã³ãŒãã«ã¯éèŠãªéšåã 2 ã€ãããŸã:
lifetime_separatorã«æž¡ããŠããã¯ããŒãžã£ã®impl for<'a>å¶çŽãPhantomDataã®ãã©ã¡ãŒã¿ã§ã©ã€ãã¿ã€ã ã䜿ã£ãŠããæ¹æ³ã
ã¯ããŒãžã£ã«å¯Ÿãã for<'a> å¶çŽ
-
ããã§ã¯
for<'a>ãã颿°åã«ã©ã€ãã¿ã€ã ã®ãžã§ããªãã¯ãã©ã¡ãŒã¿ãå°å ¥ãããã®é¢æ°æ¬äœãå¯èœãªãã¹ãŠã®ã©ã€ãã¿ã€ã ã§åäœããããšãèŠæ±ããææ®µãšããŠäœ¿ã£ãŠããŸããããã«ãã£ãŠã颿°åŒæ°ã®ãã®ç¹å®ã®ã©ã€ãã¿ã€ã ã«ã€ããŠã³ã³ãã€ã©ãç«ãŠãããä»®å®ãäžéšåãé€ãããŸãããšããã®ããåŒæ°ãå®éã«ã¯ã©ã®ã©ã€ãã¿ã€ã ãæã€ããšã«ãªããšããŠããRust ã® borrow checking ã«ãŒã«ãæºãããªããã°ãªããªãããã§ããå®éã®ã©ã€ãã¿ã€ã ãä»£å ¥ããã®ã¯åŒã³åºãåŽã§ããã颿°èªèº«ã§ã¯ãããŸããã
ããã¯æ°åŠã«ãããå šç§°éååïŒâ±¯ïŒããå倿°ãšããŠ
<T>ãå°å ¥ããããæ¹ã«äŒŒãŠããŸããããã¬ã€ãå¢çã«ãããã©ã€ãã¿ã€ã ã«å¯ŸããŠã ãé©çšãããŸããå
Tã«å¯ŸããŠãžã§ããªãã¯ãªé¢æ°ãæžããšãã颿°ã®å éšãããã®åã倿ããããšã¯ã§ããŸãããããšãã°ãåãåã® 2 ã€ã®åŒæ°ã§é¢æ°fn foo<T, U>(first: T, second: U)ãåŒã³åºãããšããŠãããã®é¢æ°ã®æ¬äœããTãšUãåãåãã©ããã¯å€æã§ããŸãããããã«ãããAPI ã®å©çšè ãèªåã§ã©ã€ãã¿ã€ã ãå®çŸ©ããŠããã¡ãã課ãããå¶çŽãåé¿ã§ããŠããŸãããšãé²ããŸãã
PhantomData ãšã©ã€ãã¿ã€ã 倿§
-
PhantomDataã¯ãã§ã«ç¥ã£ãŠããŸããããã¯ãããã§ãªããã°æªäœ¿çšã«ãªãåãã©ã€ãã¿ã€ã ãã©ã¡ãŒã¿ãã圢åŒäžã ã䜿çšããŠããããšã«ã§ããŸãã -
質å:
PhantomDataã§äœãã§ããŸããïŒæ³å®ãããåç: Typestate ãã¿ãŒã³ãææãããå€å士ã®ã©ã€ãã¿ã€ã ãçµã³ä»ããããšã
-
質å: ä»ã®èšèªã«ããããµãã¿ã€ãã³ã°ãšã¯äœã§ããïŒ
æ³å®ãããåç: ç¶æ¿ã
BãAã®ããµãã¿ã€ãããªã®ã§ãåAã®å€ãæ±ããããå Žæã§åBã®å€ã䜿ããããšã -
Rust ã«ããµãã¿ã€ãã³ã°ã¯ãããŸãïŒ ãã ãã©ã€ãã¿ã€ã ã«å¯ŸããŠã ãã§ãã
質å: ããã©ã€ãã¿ã€ã ãå¥ã®ã©ã€ãã¿ã€ã ã®ãµãã¿ã€ãã ãšããããããã¯äœãæå³ããã§ããããïŒ
ããã©ã€ãã¿ã€ã ãå¥ã®ã©ã€ãã¿ã€ã ã®ããµãã¿ã€ããã§ããã®ã¯ããã®ã©ã€ãã¿ã€ã ãçžæã®ã©ã€ãã¿ã€ã ãã é·ãåç¶ãããšã ã§ãã
-
PhantomDataã§äœ¿ãããã©ã€ãã¿ã€ã ã®æ¯ãèãã¯ããã®ã©ã€ãã¿ã€ã ãã©ããããæ¥ãããã ãã§ãªããåç §ãã©ã®ããã«å®çŸ©ãããŠãããã«ãäŸåããŸãããããã³ã³ãã€ã«ã§ããŠããŸãçç±ã¯ã
InvariantLifetimeã®äžã«ããã©ã€ãã¿ã€ã ã® å€æ§ ãç·©ãããããã§ããæ³š: ããã§åè¬è ã«å€æ§ãå®å šã«çè§£ããŠãããããšã¯æåŸ ããªãããšãããã§ã¯ãã©ã€ãã¿ã€ã ããµãã¿ã€ãé¢ä¿ã確ç«ã§ãã床åãã«å¯Ÿãããå¶çŽã®åŒ·ãã®ã¯ããã®ãããªãã®ãšããŠæ±ã£ãŠãã ããã
-
質å: ããããã£ãšå¶çŽã®åŒ·ããã®ã«ããã«ã¯ã©ãããã°ããã§ããããïŒ Rust ã§ã¯åç §åãã©ãããã°ããå¶çŽçã«ã§ããŸããïŒ
æ³å®ãããåçãŸãã¯å®æŒ:
&'id mut ()ã«ããããšããã ããããã ãã§ã¯ååã§ã¯ãããŸããïŒå¿ èŠãªã®ã¯ãã©ã€ãã¿ã€ã ã«ã€ããŠãåäžã®ã©ã€ãã¿ã€ã ã§ããå Žåãé€ããŠãµãã¿ã€ãã³ã°ãæšè«ã§ããªã 倿§ ã䜿ãããšã§ããã€ãŸããã³ã³ãã€ã©ã
'aã®ãµãã¿ã€ããšããŠèªèã§ããã®ã¯'aèªèº«ã ãã§ããæ³š: ç¹°ãè¿ããŸãããã¯ã©ã¹å šäœã«å€æ§ãçè§£ãããããšã¯ããªãã§ãã ãããä»ã®ãšããã¯ããããå¶çŽã®åŒ·ãã®ã¯ãããšããŠæ±ã£ãŠãã ããã
宿Œ:
&'id ()ïŒã©ã€ãã¿ã€ã ãšåã®äž¡æ¹ã§å ±å€ïŒã&'id mut ()ïŒã©ã€ãã¿ã€ã ã§ã¯å ±å€ãåã§ã¯äžå€ïŒã*mut &'id mut ()ïŒã©ã€ãã¿ã€ã ãšåã®äž¡æ¹ã§äžå€ïŒãæåŸã«*mut &'id ()ïŒã©ã€ãã¿ã€ã ã§ã¯äžå€ã ããåã«ã€ããŠã¯äžå€ã§ã¯ãªãïŒãžãšå€ããŠãããæåŸã® 2 ã€ã¯ã³ã³ãã€ã«ã§ããªãã¯ãã§ãããããã«ãã£ãŠããã®æèã§ã¯äºãã«æ¯èŒã§ããªãããã©ã€ãã¿ã€ã ã
PhantomDataã«çµã³ä»ããåè£ãã€ãã«èŠã€ããããšã«ãªããŸããçç±:
*mut㯠å¯å€çãã€ã³ã¿ ãæå³ããŸããRust ã«ã¯å¯å€ãã€ã³ã¿ããããŸãïŒ ããã safe Rust ã§ã¯ããã«ã€ããŠæšè«ã§ããŸãããã©ã€ãã¿ã€ã ãæã€åç §ãžã®å¯å€çãã€ã³ã¿ã«ããããšã§ãborrow checker ã®äžã§ã¯å¯å€çãã€ã³ã¿ã«ã€ããŠæšè«ã§ããªããããã³ã³ãã€ã©ããµãã¿ã€ãé¢ä¿ã倿ããã®ãé£ãããªããŸãã -
ãŸãšã: ã³ã³ãã€ã©ãã©ã€ãã¿ã€ã ããåå䌌ãŠããããšå€æããªãããã«ããæ¹æ³ãå°å ¥ããŸãããå ·äœçã«ã¯ããã®ã¹ã©ã€ããã³ã³ãã€ã«ã§ããªãããã«ããã®ã«ååå¶çŽã®åŒ·ãã
PhantomDataã«ãããã©ã€ãã¿ã€ã ã®å€æ§ãéžã¶ãšããããšã§ããã€ãŸããåãã¹ã³ãŒãå ã«åæã«ååšã§ãã倿°ããããŸãå€ãã®ãã€ã©ãŒãã¬ãŒããªãã«ã倿°ããšã«èªåçã«äºãã«ç°ãªãåã«ã§ããããã«ãªã£ãã®ã§ãã
ããã«æ¢ãããš
for<'a>éååã¯é¢æ°åã®ããã ãã®ãã®ã§ã¯ãããŸããããã㯠é«éãã¬ã€ãå¢ç ã§ãã
ãã©ã³ãä»ãåã®å®è£ (ãã©ã³ãå 3/4)
ãã©ã³ãä»ãåã®æ§ç¯æ¹æ³ã¯ããã©ã³ããªãã®åã®æ§ç¯æ¹æ³ãšã¯ç°ãªããŸãã
// Copyright 2025 Google LLC // SPDX-License-Identifier: Apache-2.0 use std::marker::PhantomData; #[derive(Default)] struct InvariantLifetime<'id>(PhantomData<*mut &'id ()>); struct ProvenIndex<'id>(usize, InvariantLifetime<'id>); struct Bytes<'id>(Vec<u8>, InvariantLifetime<'id>); impl<'id> Bytes<'id> { fn new<T>( // ãã®ã³ã³ããã¹ãã§å€æŽãããããŒã¿ã bytes: Vec<u8>, // `Bytes` ã®ã©ã€ãã¿ã€ã ã«äžæã®ãã©ã³ããä»äžãã颿° f: impl for<'a> FnOnce(Bytes<'a>) -> T, ) -> T { f(Bytes(bytes, InvariantLifetime::default()),) } fn get_index(&self, ix: usize) -> Option<ProvenIndex<'id>> { if ix < self.0.len() { Some(ProvenIndex(ix, InvariantLifetime::default())) } else { None } } fn get_proven(&self, ix: &ProvenIndex<'id>) -> u8 { debug_assert!(ix.0 < self.0.len()); unsafe { *self.0.get_unchecked(ix.0) } } }
-
åæ©: ããåã«å¯ŸããŠãèšŒææžã¿ã€ã³ããã¯ã¹ããæããããäžæ¹ã§ããããã® ã€ã³ããã¯ã¹ãåãåã®å¥ã®å€æ°ã§äœ¿ããŠããŸã£ãŠã»ãããããŸããããŸãããããã® ã€ã³ããã¯ã¹ãã¹ã³ãŒãã®å€ãžéããŠããŸãããšãé¿ãããã§ãã
ä»åã®ãã©ã³ãä»ãåã¯
Bytes: ãã€ãé åã§ããä»åã®ãã©ã³ãä»ãããŒã¯ã³ã¯
ProvenIndex: ç¯å²å ã§ããããšãåãã£ãŠãã ã€ã³ããã¯ã¹ã§ãã -
ãã®å®è£ ã«ã¯æ³šç®ãã¹ãç¹ãããã€ããããŸã:
newã¯Bytesãè¿ããã代ããã«ãéå§ããŒã¿ããšãäžåºŠã ã䜿ããã åŒã³åºããããšãã«Bytesãæž¡ãããã¯ããŒãžã£ãåãåããŸãã- ãã®
new颿°ã¯ããã¬ã€ãå¢çã«for<'a>ãæã£ãŠããŸãã - ã€ã³ããã¯ã¹ãååŸãã getter ãšãèšŒææžã¿ã€ã³ããã¯ã¹ã§å€ãååŸãã getter ã®äž¡æ¹ããããŸãã
-
åã: ãªã
newã¯Bytesãè¿ããªãã®ã§ãããã?çã:
Bytesã«ã¯ API ãå¶åŸ¡ããäžæãªã©ã€ãã¿ã€ã ãæãããå¿ èŠãããããã§ãã -
åã: ã§ã¯ã
new()ãBytesãè¿ãããã©ããªãã®ã§ãããã? å ·äœçã«ã¯ã©ã®ãããªåé¡ã çããŸãã?çã: ä»®ã«ãã®
new()ã¡ãœããããããšããŠããã®ã·ã°ããã£ãèããŠã¿ãŠãã ãã:fn new<'a>() -> Bytes<'a> { ... }ããã§ã¯ API ã®å©çšè ãã©ã€ãã¿ã€ã
'aãäœã«ãããéžã¹ãŠããŸããç°ãªãBytesã®ã€ã³ã¹ã¿ã³ã¹éã®ã©ã€ãã¿ã€ã ãäžæã§ãããäºãã«ãµãã¿ã€ãå ã§ããªãããšãä¿èšŒããèœåã倱ãããŸãã -
åã: ãªã
get_indexãšget_provenã®äž¡æ¹ãå¿ èŠãªã®ã§ãããã?æ³å®ãããçã: ãããã€ã³ããã¯ã¹ãæå¹ãã©ããã¯ã³ã³ãã€ã«æã«ã¯åãããªãããã
åã: ã§ã¯ãèšŒææžã¿ã€ã³ããã¯ã¹ã«ã¯ã©ããªæå³ãããã®ã§ãããã?
çã: å¢çãã§ãã¯ãé¿ãã€ã€ãã©ã®ã€ã³ããã¯ã¹ãæå¹ããšããç¥èãåã ã® å€æ°ããšã«ä¿æãã誀ã£ãŠå¥ã®å€æ°ã«å¯ŸããŠäœ¿ããªãããã«ããããã§ãã
泚: çŠç¹ã¯å¢çãã§ãã¯ã®éå°ãªäœ¿çšãé¿ããããšã ãã§ã¯ãªããã€ã³ããã¯ã¹ã å¥ã®å€æ°ãžããŸããã£ãŠã䜿ãããã®ãé²ãããšã«ããããŸãã
å®éã® Branded TypesïŒBranding 4/4ïŒ
// Copyright 2025 Google LLC // SPDX-License-Identifier: Apache-2.0 use std::marker::PhantomData; #[derive(Default)] struct InvariantLifetime<'id>(PhantomData<*mut &'id ()>); struct ProvenIndex<'id>(usize, InvariantLifetime<'id>); struct Bytes<'id>(Vec<u8>, InvariantLifetime<'id>); impl<'id> Bytes<'id> { fn new<T>( // ãã®ã³ã³ããã¹ãã§å€æŽãããããŒã¿ã bytes: Vec<u8>, // `Bytes` ã®ã©ã€ãã¿ã€ã ãäžæã«ãã©ã³ãåãã颿° f: impl for<'a> FnOnce(Bytes<'a>) -> T, ) -> T { f(Bytes(bytes, InvariantLifetime::default())) } fn get_index(&self, ix: usize) -> Option<ProvenIndex<'id>> { if ix < self.0.len() { Some(ProvenIndex(ix, InvariantLifetime::default())) } else { None } } fn get_proven(&self, ix: &ProvenIndex<'id>) -> u8 { self.0[ix.0] } } fn main() { let result = Bytes::new(vec![4, 5, 1], |mut bytes_1| { Bytes::new(vec![4, 2], |mut bytes_2| { let index_1 = bytes_1.get_index(2).unwrap(); let index_2 = bytes_2.get_index(1).unwrap(); bytes_1.get_proven(&index_1); bytes_2.get_proven(&index_2); // bytes_2.get_proven(&index_1); // âðš "èšç®ãå®äºããŸããïŒ" }) }); println!("{result}"); }
-
ããã§å®è£ ã®æºåãæŽã£ãã®ã§ãæ¢åã®ã€ã³ããã¯ã¹ã®èšŒæã§ããããŒã¯ã³åã倿°éã§å ±æã§ããªãããã°ã©ã ãæžããããã«ãªããŸããã
-
ãã¢:
bytes_2.get_proven(&index_1);ã®è¡ã®ã³ã¡ã³ããå€ããç°ãªã倿°ã®ã€ã³ããã¯ã¹ã䜿çšãããšã³ã³ãã€ã«ã§ããªãããšã瀺ããŠãã ããã -
åã: èšŒææžã¿ã€ã³ããã¯ã¹ãçæããããšãä¿èšŒã§ããæäœã«ã¯ãã©ã®ãããªãã®ãããã§ããããã
pushã®å®è£ ãæåŸ ãããŸãããã¢æ¡:#![allow(unused)] fn main() { // Copyright 2025 Google LLC // SPDX-License-Identifier: Apache-2.0 fn push(&mut self, value: u8) -> ProvenIndex<'id> { self.0.push(value); ProvenIndex(self.0.len() - 1, InvariantLifetime::default()) } } -
åã: ãããåãªããã€ãé åã§ã¯ãªãã
Vec<T>ã®äžè¬çãªã©ãããŒã«ã§ããã§ãããããç°¡åã§ã: ã§ããŸãïŒ
ãã¢æ¡:
Bytes<'id>ãBrandedVec<'id, T>ã«äžè¬åãã -
åã: ãã®ãããªãã®ã¯ãã»ãã«ã©ã®ãããªé åã§äœ¿ããã§ããããã
-
ãã®çµæåŸãããããŒã¯ã³ API 㯠éåžžã«å¶çŽã匷ã ãã®ã§ãããRust ã®åã·ã¹ãã å ã§å®å šã§ãããšèšŒæå¯èœã«ãªãäºæã«ã¯ãååã«æå³ããããŸãã
ããã«æ¢ã
-
GhostCell ã¯ãRust ã«ãããŠå®å šãªåŸªç°ããŒã¿æ§é ïŒãããããŸã§è¡šçŸãé£ããã£ãã»ãã®ããŒã¿æ§é ïŒãå¯èœã«ããæ§é ã§ããããã®çš®ã®ããŒã¯ã³åã䜿ã£ãŠããããã®äŸã§ç€ºããæäœã«äŒŒãåŠçãå®å šã§ãããšåãã£ãŠããã³ã³ããã¹ãããã»ã«ããéãåºããããšããªãããã«ããŠããŸãã
ãã®ãBranded Typesãã¹ã©ã€ãé£äœã¯ãè«æäžã®
BrandedVecå®è£ ã«åºã¥ããŠããããã®ãŠãŒã¹ã±ãŒã¹ã®å®è£ 詳现ã®å€ãããGhostCellèªäœãå®éã«ã©ã®ããã«å®è£ ã»å©çšãããããçè§£ããããã®ç©ãããªå°å ¥ãšããŠãããæ·±ãæ±ã£ãŠããŸããGhostCell ã¯ãŸãããã®çš®ã®ã³ã³ããã¹ãïŒã©ã€ãã¿ã€ã ã®ãã©ã³ãåïŒã§èš±å¯ãããããšãå®å šã§ããããšã蚌æããããã«ãRust ã®åã·ã¹ãã ã®å€åŽã§ã圢åŒçãªæ€èšŒãå©çšããŠããŸãã
ããªã¢ãŒãã£ãºã
// Copyright 2025 Google LLC // SPDX-License-Identifier: Apache-2.0 pub trait Trait {} pub struct HasGeneric<T>(T); pub enum Either<A, B> { Left(A), Right(B), } fn takes_generic<T: Trait>(value: &T) {} fn takes_dyn(value: &dyn Trait) {}
-
Rust ã«ã¯ããªã¢ãŒãã£ãã¯ãªã³ãŒããèšè¿°ããŠå©çšããããã®ä»çµã¿ãè±å¯ã«ãããŸããã ãããã¯ä»ã®äžè¬çãªèšèªãšã¯ããç°ãªããŸãã
-
ãã®ç« ã§ã¯ãRust ã®ããªã¢ãŒãã£ãºã ã®è©³çްãšããããä»ã®èšèªãš ã©ã®ããã«äŒŒãŠããã®ãããããã¯ã©ã®ããã«ç°ãªãã®ãã説æããŸãã
ãããã
Rust ã®ãžã§ããªã¯ã¹ãšããªã¢ãŒãã£ãºã ã®åºæ¬çãªæ©èœã
// èäœæš© 2025 Google LLC // SPDX-License-Identifier: Apache-2.0 pub struct HasGenerics<T>(...); pub fn uses_traits<T: Debug>(input: T) {...} pub trait TraitBounds: Clone {...}
- ãã®ã»ã¯ã·ã§ã³ã§ã¯ãRust ã®ããªã¢ãŒãã£ãºã ã«å¯Ÿããã¢ãããŒãã®äžæ žãšãªã æŠå¿µãã€ãŸãæ¥åžžçãªäœ¿çšã§æãããééãããã®ãèŠãŠãããŸãã
ãã¬ã€ãããããã³ã«ãã€ã³ã¿ãŒãã§ãŒã¹
// Copyright 2025 Google LLC // SPDX-License-Identifier: Apache-2.0 trait Receiver { fn send(&self, message: &str); } struct EmailAddress(String); impl Receiver for EmailAddress { fn send(&self, message: &str) { println!("Email to {}: {}", self.0, message); } } struct ChatId { uuid: [u8; 16], } impl Receiver for ChatId { fn send(&self, message: &str) { println!("Chat message sent to {:?}: {}", self.uuid, message); } }
-
Rust ã«ãããå€çžæ§ãšãžã§ããªã¯ã¹ã®æŠå¿µã¯ããã¬ã€ããäžå¿ã«å€§ããæ§ç¯ãããŠããŸãã
-
ãã¬ã€ãã¯ããžã§ããªãã¯ãªæèã§åã«å¯ŸããŠèª²ãããèŠä»¶ã§ãã
-
èŠä»¶ã¯ãã³ã³ãã€ã«æã«æ€æ»ãããããã¯ã¿ã€ãã³ã°ã«ãã䌌ããã®ãšããŠæ©èœããŸãã
ããã¯ã¿ã€ãã³ã°ã¯ãPython ã®ãããªåçã§åãªãã®èšèªã®å®è·µã«ç±æ¥ãã æŠå¿µã§ããã¢ãã«ã®ããã«æ©ããã¢ãã«ã®ããã«é³Žããªããããã¯ã¢ãã«ã ã ãšãããã®ã§ãã
ã€ãŸãã颿°ãæåŸ ããã¡ãœããããã£ãŒã«ããæã€åã¯ãã©ãããã®é¢æ°ã« ãšã£ãŠæå¹ãªå ¥åã§ããããåãã¡ãœãããå®è£ ããŠããã°ãããã¯ã¿ã€ãã³ã°ã® æèã§ã¯ãã®åãšããŠæ±ãããŸãã
ãã¬ã€ãã¯éçãªããã¯ã¿ã€ãã³ã°ã®ä»çµã¿ã®ããã«æ¯ãèããåã§ã¯ãªã æ¯ãèããæå®ããŸãããã ãããã®æ¯ãèããæ¬åœã«ååšãããã©ããã ã³ã³ãã€ã«æã«æ€æ»ã§ããŸãã
-
å¥ã®èŠæ¹ããããšããã¬ã€ãã¯åœé¡ã®éãŸãã®ãããªãã®ã§ãããããåã«å¯Ÿã㊠ãã¬ã€ããå®è£ ããããšã¯ããã®ãã¬ã€ããèŠæ±ãããããããå Žæã§ãã®åã 䜿çšã§ããããšã®èšŒæã§ãã
ãã¬ã€ãã«ã¯å¿ é ã¡ãœãããããããããã®ã¡ãœãããå®è£ ããããšãããã åãå¿ èŠãªæ¯ãèããåããŠããããšã®èšŒæã«ãªããŸãã
åè:
- https://doc.rust-lang.org/reference/items/traits.html
ãžã§ããªã¯ã¹ã«å¯Ÿãããã¬ã€ãå¢ç
// Copyright 2025 Google LLC // SPDX-License-Identifier: Apache-2.0 use std::fmt::Display; fn print_with_length<T: Display>(item: T) { println!("Item: {}", item); println!("Length: {}", item.to_string().len()); } fn main() { let number = 42; let text = "Hello, Rust!"; print_with_length(number); // æŽæ°ã§ãåäœããŸã print_with_length(text); // æååã§ãåäœããŸã }
-
ãã¬ã€ãã¯ã颿°ãã¡ãœããã®ãžã§ããªãã¯åãã©ã¡ãŒã¿ã«å¯Ÿããå¢çãšããŠäœ¿ãããããšãæãäžè¬çã§ãã
ãžã§ããªãã¯åãã©ã¡ãŒã¿ã«ãã¬ã€ãå¢çããªããšã颿°ãã¡ãœãããèšè¿°ããããã«å©çšã§ããæ¯ãèãã«ã¢ã¯ã»ã¹ã§ããŸããã
ãã¬ã€ãå¢çã䜿ããšãåããžã§ããªãã¯ãªã³ãŒãã§æ©èœããããã«å¿ èŠãªæå°éã®æ¯ãèããæå®ã§ããŸãã
åç §:
- https://doc.rust-lang.org/reference/trait-bounds.html
ãã¬ã€ãã®å°åº
// Copyright 2025 Google LLC // SPDX-License-Identifier: Apache-2.0 #[derive(Debug, PartialEq, Eq, PartialOrd, Ord)] struct BufferId([u8; 16]); #[derive(Debug, PartialEq, Eq, PartialOrd, Ord)] struct DrawingBuffer { target: [u8; 16], commands: Vec<String>, }
-
å€ãã®ãã¬ã€ãããããã³ã«ãã€ã³ã¿ãŒãã§ãŒã¹ã«ã¯ãèªæãªå®è£ ãããã ãããã¯æ©æ¢°çã«ç°¡åã«æžããŸãã
-
åã®å®çŸ©ïŒãã®æ§ææšïŒã¯æç¶ããã¯ã ïŒã³ã³ãã€ã©ãã©ã°ã€ã³ïŒã«æž¡ããŠããã¬ã€ãå®è£ ãèªåçæã§ããŸãã
ãããã®ãã¯ãã¯èª°ããäœæããªããã°ãªãããã³ã³ãã€ã©ã ãã¹ãŠãèªåã§çè§£ã§ããããã§ã¯ãããŸããã
-
å€ãã®ãã¬ã€ãã«ã¯ãçŽ æŽã§æçœãªå®è£ ããããŸããã»ãšãã©ã¯ã ãã¹ãŠã®ãã£ãŒã«ããŸãã¯ããªã¢ã³ãããã§ã«ãã®ãã¬ã€ããå®è£ ããŠããããšã«äŸåããå®è£ ã§ãã
PartialEq/Eqã¯ããã®ãã¹ãŠã®ãã£ãŒã«ã / ããªã¢ã³ãã ãããã®ãã¬ã€ããå®è£ ããŠããåã§ããã°ãããªãç°¡åã«å°åºã§ããŸãããã£ãŒã«ã / ããªã¢ã³ãã察å¿ãããŠäžŠã¹ãã©ãã 1 ã€ã§ãäžèŽããªããã°ã ç䟡æ§ãã§ãã¯ã¯ false ãè¿ããŸãã -
derive ã䜿ããšãæ©æ¢°çãã€äºæž¬å¯èœãªåœ¢ã§ãã€ã©ãŒãã¬ãŒããé¿ããããŸããderive å®è£ ã®äœè ã¯ããã®ãã¬ã€ãã®äœè ã§ããããå°ãªããšããã¬ã€ãã®é©åãªæå³è«ã念é ã«çœ®ã㊠derive ãå®è£ ããŠããå¯èœæ§ãé«ãã§ãã
-
ã¯ã©ã¹ã«è³ªåãã: ã»ãšãã©ã®ã³ãŒããèªæãªãã€ã©ãŒãã¬ãŒãã§ãã ã³ãŒãããŒã¹ããåŠçãæ±ã£ãããšã¯ãããŸããïŒ
-
ãã㯠Haskell ã®
derivingã·ã¹ãã ã«äŒŒãŠããŸãã
åèè³æ:
- https://doc.rust-lang.org/reference/attributes/derive.html#r-attributes.derive
ããã©ã«ãã®ã¡ãœããå®è£
// Copyright 2025 Google LLC // SPDX-License-Identifier: Apache-2.0 pub trait CollectLeaves { type Leaf; // å¿ é ã¡ãœãã fn collect_leaves_buffered(&self, buf: &mut Vec<Self::Leaf>); // ããã©ã«ãå®è£ fn collect_leaves(&self) -> Vec<Self::Leaf> { let mut buf = vec![]; self.collect_leaves_buffered(&mut buf); buf } }
-
ãã¬ã€ãã«ã¯ãå¿ èŠãªã¡ãœãããå®è£ ãããšããã§ã«å®è£ æžã¿ã®ã¡ãœããã å©çšã§ãããã®ããããããŸãã
-
ãã¬ã€ãã¡ãœããã¯ã颿°æ¬äœãååšããå Žåãããã©ã«ãå®è£ ãæã¡ãŸãã ãã®å®è£ ã¯ããã®ãã¬ã€ãå ã®ä»ã®ã¡ãœãããã¹ãŒããŒãã¬ã€ãã®ã¡ãœãããªã©ã å©çšå¯èœãªä»ã®ã¡ãœãããçšããŠèšè¿°ã§ããŸãã
-
å€ãã®å Žåãå®è£ ã«å¿ èŠãªå€§ãŸããªæ©èœãæäŸããã¡ãœããïŒ
Ordã®compareãªã©ïŒã«å¯ŸããŠããããã®ã¡ãœãããçšããŠå®è£ ã§ãã颿° ïŒOrdã®max/min/clampãªã©ïŒã®ããã©ã«ãå®è£ ãçšæãããŠããŸãã -
derive ãã¯ãã¯å®è£ å ã«ä»»æã® AST ãçæãããããããã©ã«ãã¡ãœãã㯠derive ãã¯ãã«ãã£ãŠãªãŒããŒã©ã€ãã§ããŸãã
åç §:
- https://doc.rust-lang.org/reference/items/traits.html#r-items.traits.associated-item-decls
ã¹ãŒããŒãã¬ã€ã / ãã¬ã€ãã®äŸåé¢ä¿
ãã¬ã€ãã¯æ°ãããã¬ã€ãã«ãã£ãŠæ¡åŒµã§ããŸãã
// èäœæš© 2025 Google LLC // SPDX-License-Identifier: Apache-2.0 pub trait Animal { /* ãã¹ãŠã®åç©ã«å ±éã®ã¡ãœãã */ } pub trait Mammal: Animal { /* åºä¹³é¡å°çšã®ã¡ãœãã */ } // stdlib ãã pub trait Ord: Eq + PartialOrd { /* Ord çšã®ã¡ãœãã */ }
-
ãã¬ã€ããäœæãããšãã¯ãåãããããŠå®è£ ããªããã°ãªããªããã¬ã€ããæå®ã§ããŸããããã㯠ã¹ãŒããŒãã¬ã€ã ãšåŒã°ããŸãã
äžã®äŸã§ã¯ã
Mammalãå®è£ ããåã¯ãã¹ãŠAnimalãå®è£ ããªããã°ãªããŸããã -
ãã®ãããªãã¬ã€ãã®éå±€ã«ãããè€éãªçŸå®äžçã®åé¡äœç³»ïŒåç©çžããã·ã³ããŒããŠã§ã¢ããªãã¬ãŒãã£ã³ã°ã·ã¹ãã åºæã®äºé ãªã©ïŒã®æ¯ãèããäžå¿ã«ã·ã¹ãã ãèšèšã§ããŸãã
-
ããã¯ãªããžã§ã¯ãç¶æ¿ãšã¯å¥ç©ã§ãïŒ ãã ããèŠãç®ã¯äŒŒãŠããŸãã
-
ãªããžã§ã¯ãç¶æ¿ã§ã¯ãªãŒããŒã©ã€ããå¯èœã§ãç¶æ¿ããåã®æ¯ãèããããã©ã«ãã§åã蟌ãŸããŸãã
-
ãã¬ã€ããã¹ãŒããŒãã¬ã€ããæã£ãŠããŠãããã®ãã¬ã€ããã¡ãœããå®è£ ãããã©ã«ãå®è£ ãšããŠãªãŒããŒã©ã€ãã§ããããšãæå³ããããã§ã¯ãããŸããã
-
åè:
- https://doc.rust-lang.org/reference/items/traits.html?highlight=supertrait#r-items.traits.supertraits
ãã©ã³ã±ãããã¬ã€ãå®è£
ãã¬ã€ããããŒã«ã«ã§ããã°ã奜ããªã ãå€ãã®åã«å¯ŸããŠå®è£ ã§ããŸãããããã©ããŸã§é²ããããã§ããããïŒ
// èäœæš© 2025 Google LLC // SPDX-License-Identifier: Apache-2.0 pub trait PrettyPrint { fn pretty_print(&self); } // ãã©ã³ã±ããå®è£ ã§ãïŒ äœãã Display ãå®è£ ããŠããã°ã // PrettyPrint ãå®è£ ããŠããããšã«ãªããŸãã impl<T> PrettyPrint for T where T: std::fmt::Display, { fn pretty_print(&self) { println!("{self}") } }
-
ãã¬ã€ãã®å®çŸ©ç®æã§ã¯ããã¬ã€ãå®è£ ã®å¯Ÿè±¡ã¯äœã§ãããŸãããå¢çã®ãªã
Tãå«ãŸããŸããäœãåãããªã
Tã«å¯ŸããŠã¯äœãã§ããªããããããã¯äžè¬çã§ã¯ãããŸããã -
æ¡ä»¶ä»ããã©ã³ã±ããå®è£ ã¯ãã¯ããã«æçšã§ãèŠããããèªåã§æžãããããæ©äŒãå€ãã§ãããã
ããããå®è£ ã§ã¯ã
impl <T: Display> ToString for T {...}ã®ããã«ããã¬ã€ãã«å¢çãä»ããŸããäžã®äŸã§ã¯ãDisplay ãå®è£ ãããã¹ãŠã®åã«å¯Ÿãããã©ã³ã±ããå®è£ ããããŸãããã®å®è£ ããã¬ã€ãå¢çããå©çšã§ããæ å ±ã¯ 1 ã€ã§ã
Display::fmtãå®è£ ããŠããããšã§ããããã¯ãã³ã³ãœãŒã«ã«æŽåœ¢è¡šç€ºããå®è£ ãæžãã«ã¯ååã§ãã
-
ãã ãããã®çš®ã®å®è£ ã«ã¯æ³šæããŠãã ãããçµæãšããŠãäžæµã®ãŠãŒã¶ãŒãããæå³ã®ããå®è£ ãè¡ããªããªãå¯èœæ§ããããŸãã
äžã®äŸã
Debugåãã«æžããŠããªãã®ã¯ããããããšã»ãšãã©ãã¹ãŠã®åãPrettyPrintãå®è£ ããããšã«ãªã£ãŠããŸãããã§ãããŸããDebugã¯æå³çã«DisplayãšäŒŒãŠããŸãããDebugã¯ããã人éãèªã¿ããããã®ã§ã¯ãªãããããã°åºåãç®çãšããŠããŸãã
åç §:
- https://doc.rust-lang.org/reference/glossary.html#blanket-implementation
æ¡ä»¶ä»ãã¡ãœããå®è£
// Copyright 2025 Google LLC // SPDX-License-Identifier: Apache-2.0 // åå®çŸ©ã«ã¯ãã¬ã€ãå¢çãä»ããŸããã pub struct Value<T>(T); // 代ããã«ãå¢çã¯ãã®åã®å®è£ ã«ä»ããŸãã impl<T: std::fmt::Display> Value<T> { fn log(&self) { println!("{}", self.0); } } // ããã㯠impl<T> Value<T> { // where å¥ã§ãã¬ã€ãå¢çãæå®ããŸã fn log_error(&self) where T: std::error::Error, { eprintln!("{}", self.0); } }
-
ãžã§ããªãã¯ãã©ã¡ãŒã¿ãæã€åãäœæãããšãã¯ããã®ãã©ã¡ãŒã¿ãäœã§ãããã ãŸãã¯ã©ã®ãã¬ã€ããå®è£ ããŠãããã«å¿ããŠããã®åã®å®è£ ãæžãããšãã§ããŸãã
-
ãããã®ã¡ãœããã¯ããã®åããããã®æ¡ä»¶ãæºããå Žåã«ã®ã¿å©çšã§ããŸãã
-
é åºä»ãéåã®ããã«ãå éšã®åãåžžã«
Ordã«ãããå Žåã«ã¯ã ãããåã®ãã©ã¡ãŒã¿ã«ãã¬ã€ãå¢çãä»ããããã®æšå¥šãããæ¹æ³ã§ãããããåèªäœã®å®çŸ©ã«ã¯ä»ããŸããããããããšããžã§ããªãã¯ãã©ã¡ãŒã¿ä»ãã§ ãã®åãèšåãããããããå©çšåŽã®ç®æã§åé¡ãåŒãèµ·ããããã§ãã
æ¡ä»¶ä»ãã¡ãœããå®è£ ã§ããäžå€æ¡ä»¶ã¯ååã«ç¶æã§ããŸãã
å€å ã«ãŒã«
äœãããŠãŒã¶ãŒãä»»æã®åã«å¯ŸããŠä»»æã®ãã¬ã€ãå®è£ ãæžããªãããã«ããŠããã®ã§ããããïŒ
// Copyright 2025 Google LLC // SPDX-License-Identifier: Apache-2.0 // ã¯ã¬ãŒã `postgresql-bindings` pub struct PostgresqlConn(/* 詳现 */); // `postgresql-bindings` ã«äŸåããã¯ã¬ãŒã `database-traits` pub trait DbConnection { /* ã¡ãœãã */ } impl DbConnection for PostgresqlConn {} // â , `DbConnection` ã¯ããŒã«ã«ã§ãã // `database-traits` ã«äŸåããã¯ã¬ãŒã `mycoolnewdb` pub struct MyCoolNewDbConn(/* 詳现 */); impl DbConnection for MyCoolNewDbConn {} // â , `MyCoolNewDbConn` ã¯ããŒã«ã«ã§ãã // `PostgresqlConn` ãš `DbConnection` ã¯ã©ã¡ãã `mycoolnewdb` ã«å¯ŸããŠããŒã«ã«ã§ã¯ãããŸããã // ããã§ã¯ `PostgresqlConn` ã«å¯Ÿãã `DbConnection` ã®å®è£ ã 2 ã€ã«ãªã£ãŠããŸããŸãïŒ impl DbConnection for PostgresqlConn {} // âðš
-
Rust ã®ãšã³ã·ã¹ãã ã§ã¯ããã¬ã€ããäºéã«å®è£ å¯èœã§ãã£ãŠã¯ãªããŸãããåãåã«å¯Ÿããåããã¬ã€ãã® 2 ã€ã®å®è£ ã¯ã解決çã®ãªãç«¶åã§ãã
-
1 ã€ã®ã¯ã¬ãŒãå ã§ããã°ãè€æ°ã®å®çŸ©ãæ€åºããŠçŠæ¢ããããšã§ãããé²ããŸããããããRust ãšã³ã·ã¹ãã å šäœã«ãŸãããã¯ã¬ãŒãéã§ã¯ã©ãã§ããããïŒ
-
åã¯ããã®ã¯ã¬ãŒãå ã§å®çŸ©ãããŠãããã€ãŸãã¯ã¬ãŒãã«å¯Ÿã㊠ããŒã«ã« ã§ããããããã§ãªããã®ã©ã¡ããã§ãã
ãã®äŸã®ãã¯ã¬ãŒããã§ã¯ã
PostgresqlConnã¯postgresql-bindingsã«å¯ŸããŠããŒã«ã«ã§ãããMyCoolNewDbConnã¯mycoolnewdbã«å¯ŸããŠããŒã«ã«ã§ãã -
ãã¬ã€ããåæ§ã«ããã®ã¯ã¬ãŒãå ã§å®çŸ©ãããŠãããã€ãŸãã¯ã¬ãŒãã«å¯Ÿã㊠ããŒã«ã« ã§ããããããã§ãªããã®ã©ã¡ããã§ãã
åãããã®äŸã§ã¯ã
DbConnectionãã¬ã€ãã¯database-traitsã«å¯ŸããŠããŒã«ã«ã§ãã -
äœããããŒã«ã«ã§ããã°ãããã«å¯Ÿãããã¬ã€ãå®è£ ãæžããŸãã
ãã¬ã€ããããŒã«ã«ã§ããã°ããã®ãã¬ã€ãã®å®è£ ãä»»æã®åã«å¯ŸããŠæžããŸãã
åãããŒã«ã«ã§ããã°ããã®åã«å¯Ÿããä»»æã®ãã¬ã€ãå®è£ ãæžããŸãã
-
ãããã®å¢çã®å€ã§ã¯ããã¬ã€ãå®è£ ãæžãããšã¯ã§ããŸããã
ããã«ããå®è£ ã®ãã³ããŒã¬ã³ã¹ããä¿ãããŸããã€ãŸããããåã«å¯Ÿãããããã¬ã€ãã®å®è£ ã¯ãã¯ã¬ãŒãããŸããã§ã 1 ã€ããååšã§ããŸããã
åè:
- https://doc.rust-lang.org/stable/reference/items/implementations.html#r-items.impl.trait.orphan-rule
éçã«ãµã€ãºã決ãŸãåãšåçã«ãµã€ãºã決ãŸãå
// èäœæš© 2025 Google LLC // SPDX-License-Identifier: Apache-2.0 use std::fmt::Debug; pub struct AlwaysSized<T /* : Sized */>(T); pub struct OptionallySized<T: ?Sized>(T); type Dyn1 = OptionallySized<dyn Debug>;
-
åæ©: ãµã€ãºãã³ã³ãã€ã«æã«ãããåãšããµã€ãºãå®è¡æã«ãããåãåºå¥ããŠæå®ã§ããããšã¯ã次ã®ç¹ã§æçšã§ã
-
Sizedãã¬ã€ãã¯ããµã€ãºãã³ã³ãã€ã«æã«ãããåã«å¯ŸããŠèªåçã«å®è£ ãããŸãããã®ãã¬ã€ãã¯ã
Sizedã§ããããšããªããã¢ãŠãããŠããªããã¹ãŠã®åãã©ã¡ãŒã¿ã«ãèªåçã«è¿œå ãããŸãã -
ã»ãšãã©ã®åã¯
Sizedãå®è£ ããŠããŸããã€ãŸãããããã®ãµã€ãºã¯ã³ã³ãã€ã«æã«ããããŸãã[T]ãstrãdyn Traitã®ãããªåã¯ãããããåçãµã€ãºåã§ãããããã®ãµã€ãºã¯ããã®åã®å€ãžã®åç §ã®äžéšãšããŠæ ŒçŽãããŸãã -
åãã©ã¡ãŒã¿ã¯ãç¹ã«æå®ããªãéãèªåçã«
Sizedãå®è£ ããŸãã
åè:
- https://doc.rust-lang.org/stable/reference/dynamically-sized-types.html#r-dynamic-sized
åçžåãšãã€ããªãµã€ãº
// èäœæš© 2025 Google LLC // SPDX-License-Identifier: Apache-2.0 fn print_vec<T: std::fmt::Debug>(debug_vec: &Vec<T>) { for item in debug_vec { println!("{:?}", item); } } fn main() { let ints = vec![1u32, 2, 3]; let floats = vec![1.1f32, 2.2, 3.3]; // 1ã€ç®ã®ã€ã³ã¹ã¿ã³ã¹ã&Vec<u32> -> () print_vec(&ints); // 2ã€ç®ã®ã€ã³ã¹ã¿ã³ã¹ã&Vec<f32> -> () print_vec(&floats); }
-
ãžã§ããªã¯ã¹ãæã€é¢æ°ãåã®åã€ã³ã¹ã¿ã³ã¹ã¯ãã³ã³ãã€ã«æã«äžæã§ å ·äœçãªããŒãžã§ã³ãžãšå€æãããŸãããžã§ããªã¯ã¹ã¯å®è¡æã«ã¯ååšããã ããã®ã¯å ·äœçãªåã ãã§ãã
-
ããã«ãããé«ãåºæ¬æ§èœãšæé©åã®ãããããåŸãããŸããããã®ä»£åãšã㊠ãã€ããªãµã€ãºãšã³ã³ãã€ã«æéãå¢å ããŸãã
-
ãã€ããªãµã€ãºãã³ã³ãã€ã«æéãåæžããæ¹æ³ã¯æ°å€ããããŸãããããã§ã¯ ãããã¯æ±ããŸããã
-
䜿ã£ãåã ãæ¯æã: åçžåã«ãããã€ããªãµã€ãºã®å¢å ãçºçããã®ã¯ã æçµçãªããã°ã©ã ãŸãã¯åçã©ã€ãã©ãªã§äœ¿ãããåã®ã€ã³ã¹ã¿ã³ã¹åãã ãã®åã«å¯Ÿãã颿°ã«ã€ããŠã®ã¿ã§ãã
-
æ°ã«ãã¹ãå Žé¢: åçžåã¯ã³ã³ãã€ã«æéãšãã€ããªãµã€ãºã«åœ±é¿ããŸãã ãã©ãŠã¶å ã§åã WebAssembly ãçµã¿èŸŒã¿ã·ã¹ãã éçºã®ãããªç¶æ³ã§ã¯ã ãžã§ããªã¯ã¹ãåæã«ããèšèšãæèããã»ãããããããããŸããã
OOP ãã Rust ãž: ç¶æ¿ã§ã¯ãªãã³ã³ããžã·ã§ã³
-
ç¶æ¿ã¯ããã©ãã€ã ãšããŠã® OOP ã®æåã®éµã§ããããžãã¹ããžãã¯ã® äžæ žãšããŠç¶æ¿ãçšãããæåãããœãããŠã§ã¢ãšã³ãžãã¢ãªã³ã°ãäœå幎ã«ã ããã£ãŠè¡ãããŠããŸããã
-
ã§ã¯ããªã Rust ã¯ç¶æ¿ãé¿ããã®ã§ããããïŒ
-
ç¶æ¿ããŒã¹ã®åé¡è§£æ±ºãã Rust ã®ã¢ãããŒããžãã©ã®ããã«ç§»è¡ããã° ããã®ã§ããããïŒ
-
Rust ã§ã¯ç°çš®ã³ã¬ã¯ã·ã§ã³ãã©ã®ããã«è¡šçŸããã®ã§ããããïŒ
-
ãã®ã»ã¯ã·ã§ã³ã§ã¯ãjava ã C++ ãªã©ã® OOP èšèªã«ããããåã䜿ã£ã 倿 çãªåé¡è§£æ±ºã®èãæ¹ãããPolymorphism ã«å¯Ÿãã Rust ã® ãã¬ã€ãããŒã¹ã®ã¢ãããŒããžã©ã®ããã«ç§»è¡ããããèŠãŠãããŸãã
-
éãã¯ãããŸãããå ±éããç¹ãæ°å€ããããŸããç¹ã«ãOOP éçºã® ã¢ãã³ãªæšæºãšã¯å€ããå ±æããŠããŸãããªãŒãã³ãªæ°æã¡ãä¿ã€ããšã å¿ããªãã§ãã ããã
OOPèšèªã«ãããç¶æ¿
// åºåºã¯ã©ã¹
class Vehicle {
public:
void accelerate() { }
void brake() { }
};
// ç¶æ¿ããã¯ã©ã¹
class Car : public Vehicle {
public:
void honk() { }
};
int main() {
Car myCar; // Car ãªããžã§ã¯ããäœæ
myCar.accelerate(); // ç¶æ¿ããã¡ãœãã
myCar.honk(); // Car ç¬èªã®ã¡ãœãã
myCar.brake(); // ç¶æ¿ããã¡ãœãã
return 0;
}
-
ããã¯ãä»ã®èšèªã«ãããç¶æ¿ãšã¯äœãã«ã€ããŠãåŠçåãã®çããªãã€ã³ããŒã«ããå¿ èŠããããŸãã
-
ç¶æ¿ã¯ããåãåãç¶æ¿å ã§ããã芪ãåã®ãã£ãŒã«ããšã¡ãœãããç²åŸããä»çµã¿ã§ãã
-
ã¡ãœããã¯ãå¿ èŠã«å¿ããŠç¶æ¿ããåããªãŒããŒã©ã€ãã§ããŸãã
-
superã䜿ããšãç¶æ¿å ã¯ã©ã¹ã®ã¡ãœãããåŒã³åºããŸãã
Rust ã«ç¶æ¿ããªãã®ã¯ãªãã§ããïŒ
// èäœæš© 2025 Google LLC // SPDX-License-Identifier: Apache-2.0 pub struct Id { pub id: u32 } impl Id { // ã¡ãœãã } // ðšâãRust ã«ã¯ç¶æ¿ããããŸããïŒ pub struct Data: Id { // ç¶æ¿ããã "id" ãã£ãŒã«ã pub name: String, } impl Data { // ã¡ãœããã§ãããId ã®ã¡ãœãããå«ãŸãããã // ãããã¯ãããã®ã¡ãœããããªãŒããŒã©ã€ãããå¯èœæ§ããããŸãã } // â pub struct Data { pub id: Id, pub name: String, } impl Data { // ãã¬ã€ãç±æ¥ã§ã¯ãªã Data ã®ãã¹ãŠã®ã¡ãœããã } impl SomeTrait for Data { // ãã¬ã€ãã®å®è£ ã¯å¥åã® impl ãããã¯ã«èšè¿°ããŸãã }
-
ç¶æ¿ã«ã¯ããã€ãã®æ¬ ç¹ããããŸãã
-
ããã©ã«ãã§ç°çš®ã®åãæ··åšããããã:
ã¯ã©ã¹ç¶æ¿ã§ã¯ãç°ãªãã¯ã©ã¹ã®åãæé»çã«çžäºäº€æå¯èœãªãã®ãšããŠæ±ããŸããã å ·äœçãªåããããåãå¥ã®åãšåäžã§ãããã©ãããæå®ã§ããŸããã
ããã«ãããçå€å€å®ãæ¯èŒã®ãããªæäœã§ããšã©ãŒãæãããå¥ã®åœ¢ã§ ãããã¯ãããããæ¯èŒãçå€å€å®ãèš±ãããŠããŸããŸãã
-
ããŒã¿æ§é ã®æ§æèŠçŽ ãšãã®æ¯ãèããæ±ºããæ£ãšãªãæ å ±æºãè€æ°ãã:
åã®ãã£ãŒã«ãã¯ç¶æ¿éå±€ã«ãã£ãŠèŠãã«ãããªããŸãã
åã®ã¡ãœããã¯èŠªåããªãŒããŒã©ã€ãããŠãããããããããããã¯ååã« ãã£ãŠãªãŒããŒã©ã€ãããããããããªããããè€æ°ã®åœäºè ã«ãã£ãŠä¿å® ãããè€éãªã³ãŒãããŒã¹ã§ã¯ããã®åã®æ¯ãèããææ¡ããã®ãå°é£ã§ãã
-
ããã©ã«ãã®åçãã£ã¹ãããã§ã¯ãvtable ã®ã«ãã¯ã¢ããã«ãã ãªãŒããŒããããå ãã:
åçãã£ã¹ããããæ©èœãããã«ã¯ãåŒã³åºãã¹ãã¡ãœãããããã®åã« ã€ããŠå®è¡æã«ã®ã¿åãããã®ä»ã®æ å ±ãæ ŒçŽããå Žæãå¿ èŠã§ãã
ãã®æ ŒçŽå ãããã®å€ã«å¯Ÿãã
vtableã§ããã¡ãœããåŒã³åºãã§ã¯ã ã³ã³ãã€ã«æã«åãåãã£ãŠããå Žåã®ã¡ãœããåŒã³åºããããå€ãã® éæ¥åç §ãå¿ èŠã«ãªããŸãã
Rust ã®èŠç¹ããèŠãç¶æ¿
// Copyright 2025 Google LLC // SPDX-License-Identifier: Apache-2.0 // ããŒã¿ pub struct Data { id: usize, name: String, } // å ·äœçãªæ¯ãèã impl Data { fn new(id: usize, name: impl Into<String>) -> Self { Self { id, name: name.into() } } } // æœè±¡çãªæ¯ãèã trait Named { fn name(&self) -> &str; } // å®è£ ãããæ¯ãèã impl Named for Data { fn name(&self) -> &str { &self.name } }
-
Rust ã®èŠç¹ãã€ãŸãç¶æ¿ãšãããã®ããããŸã§ååšããªãã£ãèŠç¹ãããããšã ç¶æ¿ãå°å ¥ããããšã¯ãåãšãã¬ã€ãã®å¢çãææ§ã«ããããã«èŠããŸãã
-
åã¯ãå ·äœçãªããŒã¿ãšãããã«é¢é£ä»ããããæ¯ãèãã§ãã
ãã¬ã€ãã¯ãåã«ãã£ãŠå®è£ ãããªããã°ãªããªãæœè±¡çãªæ¯ãèãã§ãã
ã¯ã©ã¹ã¯ãããŒã¿ãæ¯ãèãããããŠãã®æ¯ãèãã«å¯ŸãããªãŒããŒã©ã€ããçµã¿åããããã®ã§ãã
-
Rust ããæ¥ãç«å Žã§ã¯ãç¶æ¿å¯èœãªã¯ã©ã¹ã¯ãåã§ããããã¬ã€ãã§ããã ãã®ã®ããã«èŠããŸãã
-
ããã¯å©ç¹ã§ã¯ãããŸããããªããªããå ·äœçãªåã«ã€ããŠæšè«ã§ããªããªãããã§ãã
-
ãã® 2 ã€ãåé¢ã§ããªããšããžã§ããªãã¯ãªæ¯ãèããšå ·äœçãªè©³çްã«ã€ã㊠èããã®ãé£ãããªããŸãããªããªããOOP ã§ã¯ããã 2 ã€ã®æŠå¿µã äºãã«çµã³ä»ããããŠããããã§ãã
-
ãã©ãããªãã£ãŒã«ãã¢ã¯ã»ã¹ãåå®çŸ©ã«ããã DRY ã®å©äŸ¿æ§ã¯ã æ¯ãèããšããŒã¿ãåºå¥ããŠæžãã³ãŒããæã€æç¢ºãã倱ã代åã« èŠåããã®ã§ã¯ãããŸããã
Rust ã«ããããç¶æ¿ã: ã¹ãŒããŒãã¬ã€ã
// Copyright 2025 Google LLC // SPDX-License-Identifier: Apache-2.0 pub trait SuperTrait {} pub trait Trait: SuperTrait {}
-
Rust ã§ã¯ããã¬ã€ãã¯ã»ãã®ãã¬ã€ãã«äŸåã§ããŸãããã¬ã€ãã ã¹ãŒããŒãã¬ã€ããæãŠãããšã¯ããã§ã«ããç¥ãããŠããŸãã
-
ããã¯è¡šé¢çã«ã¯ç¶æ¿ã«äŒŒãŠããŸãã
-
ããã¯ç¶æ¿ã«äŒŒãä»çµã¿ã§ãããããŒã¿ã𠿝ãèããåé¢ããŸãã
-
æ¯ãèããææ¡ããããç¶æ ã«ä¿ã¡ãŸãã
-
ãå€éç¶æ¿ãã§å®çŸãããããšããããç°¡åã«å®çŸã§ããŸã:
ããåãã©ã®ãããªæ¯ãèããè¡ãããã ãããç§ãã¡ã¯ãã®æ¯ãèããå¿ èŠãšãã ããšãæç¢ºã«ããæç¹ã§æ°ã«ããã°ååã§ãïŒãžã§ããªãã¯ããã¬ã€ãã§å¢çä»ããããšãïŒã
ãžã§ããªãã¯ã«è€æ°ã®ãã¬ã€ããæå®ããã°ããã®åãããããã¹ãŠã®ãã¬ã€ãã® ã¡ãœãããæã€ããšãããããŸãã
-
ãã£ãŒã«ãã®ç¶æ¿ã¯é¢ä¿ããŸããããã¬ã€ãã¯ãã£ãŒã«ããå ¬éããã ã¡ãœãããšé¢é£å / 宿°ã ããå ¬éããŸãã
ç¶æ¿ããã³ã³ããžã·ã§ã³
// èäœæš© 2025 Google LLC // SPDX-License-Identifier: Apache-2.0 pub struct Uuid([u8; 16]); pub struct Address { street: String, city_or_province: String, code: String, country: String, } pub struct User { id: Uuid, address: Address, }
-
ããã¯ã¹ã€ã³ãç¶æ¿ã§ã¯ãªããç°ãªãåã®ãã£ãŒã«ããäœæããããšã§åãçµã¿åãããŸãã
ããã«ã¯æ¬ ç¹ããããäž»ã«ãã£ãŒã«ãã¢ã¯ã»ã¹ã®äœ¿ãåæã«é¢ãããã®ã§ããããã®äžæ¹ã§ãåãäœãè¡ããäœã«ã¢ã¯ã»ã¹ã§ããã®ãã«ã€ããŠãéçºè ã«å€§ããªå¶åŸ¡æ§ãšæç¢ºãããããããŸãã
-
trait ã derive ããéã¯ãstruct ã®ãã¹ãŠã®ãã£ãŒã«ãåããŸã㯠enum ã®ãã¹ãŠã®ããªã¢ã³ãåããã® trait ãå®è£ ããŠããããšã確èªããŠãã ãããderive ãã¯ãã¯ãæ°ããåãæ§æãããã¹ãŠã®åããã® trait ããã§ã«å®è£ ããŠããããšãåæãšããŠããããšããããããŸãã
Rust ã§åçãã£ã¹ããããè¡ãããã® dyn Trait
// èäœæš© 2025 Google LLC // SPDX-License-Identifier: Apache-2.0 pub trait Trait {} impl Trait for i32 {} impl Trait for String {} fn main() { let int: &dyn Trait = &42i32; let string: &dyn Trait = &String::from("Hello dyn!");; }
-
åçãã£ã¹ãããã¯ãªããžã§ã¯ãæåããã°ã©ãã³ã°ã«ãããææ³ã§ãããåã äœã§ããããããããã®åã®æ¯ãèããããéèŠããå¿ èŠãããå Žé¢ã§ãã䜿 ãããŸãã
OOP èšèªã§ã¯ãåçãã£ã¹ãããã¯å€ãã®å Žå æé»ç㪠ããã»ã¹ã§ããã ããã䜿ããªããšããéžæã¯ã§ããŸããã
Rust ã§ã¯
dyn Traitã䜿ããŸããããã¯åçãã£ã¹ãããã«æç€ºçã«åå ãã圢åŒã§ãã -
dyn äºæ ãªä»»æã®ãã¬ã€ãã«ã€ããŠããã®ãã¬ã€ããå®è£ ããå€ãžã®åç § ã
dyn Traitå€ãžå匷å¶ã§ããŸãã -
ãããã ãã¬ã€ããªããžã§ã¯ã ãšåŒã³ãŸãããã®åã¯ã³ã³ãã€ã«æã«ã¯ åãããŸãããããã®æ¯ãèããã€ãŸããã¬ã€ãèªäœã«ãã£ãŠå®çŸ©ããããã® ã¯åãã£ãŠããŸãã
-
OOP ã¹ã¿ã€ã«ã®ç°çš®ããŒã¿æ§é ã å¿ èŠãª å Žåã¯ã
Box<dyn Trait>ã䜿ã ãŸããããŸãã¯åçš®ã§ãžã§ããªã¯ã¹ããŒã¹ã«ä¿ã€ããšã詊ããŠãã ããïŒ
dynäºæã®ãã¬ã€ã
// èäœæš© 2025 Google LLC // SPDX-License-Identifier: Apache-2.0 pub trait Trait { // dynäºæ fn takes_self(&self); // dynäºæã ããdyn ã®å Žåã¯ãã®ã¡ãœããã䜿ããªã fn takes_self_and_param<T>(&self, input: &T); // dynäºæã§ã¯ãªããªã const ASSOC_CONST: i32; // dynäºæã§ã¯ãªããªã fn clone(&self) -> Self; }
-
ãã¹ãŠã®ãã¬ã€ãããã¬ã€ããªããžã§ã¯ããšããŠåŒã³åºããããã§ã¯ãããŸãããåŒã³åºãããã¬ã€ã㯠dynäºæ ãã¬ã€ããšåŒã°ããŸãã
-
以åã¯ããã object safe traits ãŸã㯠object safety ãšåŒãã§ããŸããã
-
åçãã£ã¹ãããã§ã¯ãã³ã³ãã€ã«æã®åæ å ±ã®å€ããå®è¡æã® vtable æ å ±ãžãšç§»ãããŸãã
ããæŠå¿µããvtable ã«æå³ã®ããåœ¢ã§æ ŒçŽã§ãããã®ãšäž¡ç«ããªãå Žåã ãã®ãã¬ã€ã㯠dynäºæã§ã¯ãªããªããããããã¯ãã®ã¡ãœãã㯠dyn ã³ã³ããã¹ãã§äœ¿ããªãããã«é€å€ãããŸãã
-
ãããã¬ã€ãã dynäºæã§ããã®ã¯ããã¹ãŠã®ã¹ãŒããŒãã¬ã€ãã dynäºæã§ããã é¢é£å®æ°ãé¢é£åãæããããžã§ããªã¯ã¹ã«äŸåããã¡ãœãããæããªãå Žåã§ãã
-
dynéäºæãªãã¬ã€ãã«æãããééããã®ã¯ãããããé¢é£å/é¢é£å®æ°ã æã£ãŠããå Žåãã
Selfãè¿ãå Žåã§ãïŒã€ãŸãCloneãã¬ã€ã㯠dynäºæã§ã¯ãããŸããïŒãããã¯ãé¢é£ããããŒã¿ã vtable ã«æ ŒçŽããå¿ èŠãããããã®ã¶ã 远å ã®ã¡ã¢ãªãæ¶è²»ããããã§ãã
cloneã®ãããªã¡ãœããã§ã¯ãåºååãselfã®å ·äœçãªåã«äŸåããããã ããã«ãã dynäºæã§ã¯ãªããªããŸãã
åç §:
- https://doc.rust-lang.org/1.91.1/reference/items/traits.html#r-items.traits.dyn-compatible
ãžã§ããªãã¯é¢æ°ãã©ã¡ãŒã¿ vs dyn Trait
å€çžçãªé¢æ°ãæžãã«ã¯ 2 ã€ã®æ¹æ³ããããŸããããããã¯ã©ã®ããã«æ¯èŒã§ããã§ããããïŒ
// Copyright 2025 Google LLC // SPDX-License-Identifier: Apache-2.0 fn print_display<T: std::fmt::Display>(t: &T) { println!("{}", t); } fn print_display_dyn(t: &dyn std::fmt::Display) { println!("{}", t); } fn main() { let int = 42i32; // i32 å ¥åçšã®åºæã®é¢æ°ã«åçžåãããã print_display(&int); // ååã«ã€ã 1 〠print_display_dyn(&int); }
-
ãžã§ããªã¯ã¹ãŸãã¯ãã¬ã€ããªããžã§ã¯ãã䜿ã£ãŠãå€çžçãªé¢æ°ãæžããŸãã
-
ãžã§ããªãã¯ãã©ã¡ãŒã¿ãæã€é¢æ°ãæžãå Žåããã©ã¡ãŒã¿ã«ä»£å ¥ãããåããšã«ããã®é¢æ°ã®æ°ããããŒãžã§ã³ãçæãããŸãã
ããã¯åçžåã§èŠããšããã§ãããã€ããªãµã€ãºãšåŒãæãã«ãããé«ãæé©åã®äœå°ãåŸãããŸãã
-
ãã¬ã€ããªããžã§ã¯ããåãåã颿°ãæžãå Žåããã®é¢æ°ã®ããŒãžã§ã³ã¯æçµçãªãã€ããªã«ã¯ 1 ã€ããååšããŸããïŒã€ã³ã©ã€ã³åã¯é€ããŸãïŒã
-
ãžã§ããªãã¯ãã©ã¡ãŒã¿ã¯ããã€ããªãµã€ãºãé€ãã°ãŒãã³ã¹ãã§ããåã¯å質ã§ãªããã°ãªããŸããïŒT ã®ãã¹ãŠã®ã€ã³ã¹ã¿ã³ã¹ã¯åãåã§ããããããŸããïŒã
ãã¬ã€ããªããžã§ã¯ãã®å¶é
// èäœæš© 2025 Google LLC // SPDX-License-Identifier: Apache-2.0 use std::any::Any; pub trait Trait: Any {} impl Trait for i32 {} fn main() { dbg!(size_of::<i32>()); // 4 ãã€ããææå€ dbg!(size_of::<&i32>()); // 8 ãã€ããåç § dbg!(size_of::<&dyn Trait>()); // 16 ãã€ããã¯ã€ããã€ã³ã¿ }
-
ãã¬ã€ããªããžã§ã¯ãã¯ãåé¡ã解決ããããã®éå®çãªæ¹æ³ã§ãã
-
ãã¬ã€ããªããžã§ã¯ãããå ·è±¡åãžããŠã³ãã£ã¹ããããå Žåã¯ã察象ã®ãã¬ã€ãã
Anyãã¹ãŒããŒãã¬ã€ããšããŠæã€ããšããŸãã¯ãã¬ã€ããªããžã§ã¯ããã¡ã€ã³ã®ãã¬ã€ããšAnyã®äž¡æ¹ã«å¯Ÿãããã®ã§ããããšãæå®ããå¿ èŠããããŸããããã§ããªãã
dyn MyTraitãdyn Anyã«ãã£ã¹ãããå¿ èŠããããŸãã -
ãã¬ã€ããªããžã§ã¯ãã«ã¯ã¡ã¢ãªäžã®ãªãŒããŒãããããããŸããããã¯ãã¯ã€ããã€ã³ã¿ãã§ãããããŒã¿ãã®ãã®ãžã®ãã€ã³ã¿ã ãã§ãªããvtable çšã®å¥ã®ãã€ã³ã¿ãä¿æããå¿ èŠããããŸãã
-
ãã¬ã€ããªããžã§ã¯ãã¯åçãµã€ãºä»ãåã§ãããããå®çšäžã¯åç §åãŸãã¯ãã€ã³ã¿åãä»ããŠãã䜿çšã§ããŸããã
ãã¬ã€ããªããžã§ã¯ãã䜿çšããéã«ã¯ãå€ã®ããªãã¡ã¬ã³ã¹ãšé¢é£ãããã¬ã€ãã¡ãœããã®åŒã³åºãã«é¢ããåºæ¬çãªãªãŒããŒãããããããŸãã
dyn trait ã䜿ã£ãç°çš®ããŒã¿
// Copyright 2025 Google LLC // SPDX-License-Identifier: Apache-2.0 use std::fmt::Display; pub struct Lambda; impl Display for Lambda { fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { write!(f, "λ") } } fn main() { let heterogeneous: Vec<Box<dyn Display>> = vec![ Box::new(42u32), Box::new(String::from("Woah")), Box::new(Lambda), ]; for item in heterogeneous { // "item" ã Display ãå®è£ ããŠããããšã¯åãã£ãŠããŸããããã以å€ã¯äœãåãããŸããïŒ println!("Display output: {}", item); } }
-
dyn Traitã¯åçãã£ã¹ãããã®ããã®ããŒã«ã§ãããã³ã¬ã¯ã·ã§ã³ã«ç°çš®ããŒã¿ã æ ŒçŽã§ããŸãã -
ãã®äŸã§ã¯ããã¹ãŠ
std::fmt::Displayãå®è£ ããåãæ ŒçŽãããã®ã³ã¬ã¯ã·ã§ã³å ã® ãã¹ãŠã®èŠçŽ ãç»é¢ã«åºåããŠããŸãã
Any ãã¬ã€ããšããŠã³ãã£ã¹ã
// èäœæš© 2025 Google LLC // SPDX-License-Identifier: Apache-2.0 use std::any::Any; #[derive(Debug)] pub struct ThisImplementsAny; fn take_any<T: Any>(t: &T) {} fn main() { let is_an_any = ThisImplementsAny; take_any(&is_an_any); let dyn_any: &dyn Any = &is_an_any; dbg!(dyn_any.type_id()); dbg!(dyn_any.is::<ThisImplementsAny>()); let is_downcast: Option<&ThisImplementsAny> = dyn_any.downcast_ref(); dbg!(is_downcast); }
-
Anyãã¬ã€ãã䜿ããšãå€ã dyn å€ããå ·è±¡å€ãžããŠã³ãã£ã¹ããçŽãããšãã§ããŸãã -
ãã㯠auto trait ã§ããSend/Sync/Sized ãšåæ§ã«ãç¹å®ã®æ¡ä»¶ãæºãããã¹ãŠã®åã«å¯ŸããŠèªåçã«å®è£ ãããŸãã
-
Anyã®æ¡ä»¶ã¯ãåã'staticã§ããããšã§ããã€ãŸãããã®åã®å éšã«é'staticãªã©ã€ãã¿ã€ã ãäžåå«ãŸãªããšããããšã§ãã -
Anyã¯ãé¢é£ãã 2 ã€ã®æ¯ãèããæäŸããŸããããŠã³ãã£ã¹ããšãåãåäžã§ãããã©ããã®å®è¡æãã§ãã¯ã§ããäžã®äŸã§ã¯ã
AnyããThisImplementsAnyãžèªåçã«ããŠã³ãã£ã¹ãã§ããããšãããããŸãããŸããå€ãã©ã®åã§ãããã確èªããããã«
Any::isã䜿ãããŠããããšãããããŸãã -
Anyã¯åã«å¯Ÿãããªãã¬ã¯ã·ã§ã³ãå®è£ ãããã®ã§ã¯ãªããAnyã§ã§ããã®ã¯ããã ãã§ãã
èœãšã穎: ããã« dyn Trait ã«é£ã³ã€ããŠããŸãããš
// Copyright 2025 Google LLC // SPDX-License-Identifier: Apache-2.0 use std::any::Any; pub trait AddDyn: Any { fn add_dyn(&self, rhs: &dyn AddDyn) -> Box<dyn AddDyn>; } impl AddDyn for i32 { fn add_dyn(&self, rhs: &dyn AddDyn) -> Box<dyn AddDyn> { if let Some(downcast) = (rhs as &dyn Any).downcast_ref::<Self>() { Box::new(self + downcast) } else { Box::new(*self) } } } fn main() { let i: &dyn AddDyn = &42; let j: &dyn AddDyn = &64; let k: Box<dyn AddDyn> = i.add_dyn(j); dbg!((k.as_ref() as &dyn Any).is::<i32>()); dbg!((k.as_ref() as &dyn Any).downcast_ref::<i32>()); }
-
OOP ã®ããã¯ã°ã©ãŠã³ãããæ¥ããšããã®åçãã£ã¹ããããšãã éå ·ã«ã§ããã ãæ©ãé Œãããšããã®ã¯çè§£ã§ããŸãã
-
ããã¯æšå¥šãããããæ¹ã§ã¯ãããŸããããã¬ã€ããªããžã§ã¯ãã䜿ããšã éçºè ãšã³ã³ãã€ã©ã®åæ¹ãæã£ãŠããåã«é¢ããç¥èããæè»æ§ãš åŒãæãã«ææŸãç¶æ³ã«ãªããŸãã
-
äžã®äŸã¯ãããæ¥µç«¯ãªãšãããŸã§æŒãé²ããŠããŸããæ°å€ã®å ç®ã åçãã£ã¹ãããã®ããã»ã¹ã«çžãããŠããããã»ãšãã©äœãã§ããªã ãªã£ãŠããŸãã§ãããã
ããããåçãã£ã¹ãããã¯å€ãã®ããã°ã©ãã³ã°èšèªã§ã¯ãã°ãã° é ãããŠããŸããããã§ã¯ãããããæç€ºçã«ãªã£ãŠããŸãã
AddDynã®i32å®è£ ã§ã¯ããŸãrhsåŒæ°ãi32ãšåãåãž ããŠã³ãã£ã¹ãã§ããã詊ãå¿ èŠããããããã§ãªãå Žåã¯é»ã£ãР倱æããŸããæ¬¡ã«ãæ°ããå€ãããŒãã«ç¢ºä¿ããå¿ èŠããããŸãããããåç ãã£ã¹ãããã®äžçã«ãšã©ããŠãããªãããããå¿ èŠã«ãªãããã§ãã
2 ã€ã®å€ãè¶³ãåãããããšããããèŠããå Žåã¯ããããŸã§ã®æäœã§ 課ããããã¬ã€ãå¢çã®ããããã®ãŸãŸã§ã¯åºåã§ããªãã®ã§ãåã³ åºåå¯èœãª âå®éã®â åãžããŠã³ãã£ã¹ãããªããã°ãªããŸããã
-
ã¯ã©ã¹ã«è³ªåããŠã¿ãŸããã: ãªã
mainã« Display å¢çã远å ãã ã ãã§ã¯ããã®ãŸãŸè¡šç€ºã§ããªãã®ã§ããããïŒçã:
add_dynãè¿ãã®ã¯dyn AddDynã ããªã®ã§ãåŒæ°ã®åãã æ»ãå€ã®åã«è³ããŸã§ã®éã«ããã®åãäœãå®è£ ããŠããããšããæ å ±ã 倱ã£ãŠããŸããŸããå ¥åãDisplayãå®è£ ããŠããŠããæ»ãå€ã®å㯠ããã§ã¯ãããŸããã -
ãã®çµæãããã©ãŒãã³ã¹ãäœããçè§£ããã«ããã³ãŒãã«ãªããŸã
ãŠãŒã¶ãŒãæ¡åŒµã§ããªããããªã¢ãŒãã£ãºã ã®ããã® sealed trait
// Copyright 2025 Google LLC // SPDX-License-Identifier: Apache-2.0 // ã¯ã¬ãŒã㯠"sealed" ã¢ãžã¥ãŒã«ãšãã®ãã¬ã€ãã«ã¢ã¯ã»ã¹ã§ããŸãããããã« // äŸåãããããžã§ã¯ãã¯ã¢ã¯ã»ã¹ã§ããŸããã mod sealed { pub trait Sealed {} impl Sealed for String {} impl Sealed for Vec<u8> {} //... } pub trait APITrait: sealed::Sealed { /* ã¡ãœãã */ } impl APITrait for String {} impl APITrait for Vec<u8> {}
- åæ©: ã¯ã¬ãŒãå ã§ã¯ãã¬ã€ãé§åã®ã³ãŒãã䜿ãããäžæ¹ã§ããã®ã¯ã¬ãŒãã« äŸåãããããžã§ã¯ãããã®ãã¬ã€ããå®è£ ã§ããªãããã«ãããå ŽåããããŸãã
ãªãã§ããããïŒ
çŸæç¹ã§ã¯ããã®ãã¬ã€ãã¯ããŠã³ã¹ããªãŒã ã§ã®å®è£ ã«å¯ŸããŠäžå®å®ã ãšèŠãªããã å¯èœæ§ããããŸãã
å¥ã®çç±ãšããŠã¯ããã¬ã€ãã®å®æãªå®è£ ã«å¯ŸããŠãã¡ã€ã³ã®ãªã¹ã¯ãé«ãå Žå ïŒããšãã°æå·åéïŒãæããããŸãã
-
ãããå®çŸããããã«äœ¿ãä»çµã¿ã¯ãã¹ãŒããŒãã¬ã€ããžã®ã¢ã¯ã»ã¹ãå¶éããããšã§ã ããŠã³ã¹ããªãŒã ã®ãŠãŒã¶ãŒãèªåã®åã«å¯ŸããŠãã®ãã¬ã€ããå®è£ ã§ããªãããã«ãã ãã®ã§ãã
-
ãªãåã« enum ã䜿ããªãã®ã§ããããïŒ
-
enum ã¯å®è£ ã®è©³çްãã€ãŸããããã¯ãããã®åã«å¯ŸããŠåäœããããé²åºããŸãã
-
ãŠãŒã¶ãŒã¯ API ã䜿ãããã« enum ã®ããªã¢ã³ãã³ã³ã¹ãã©ã¯ã¿ãŒã䜿ãå¿ èŠã ãããŸãã
-
ãŠãŒã¶ãŒã¯èªåã®ã³ãŒãå ã§ãã® enum ãåãšããŠäœ¿ãããšãã§ããenum ãå€æŽ ããããšãã«ã¯ããã®å€æŽã«åãããŠèªåã®ã³ãŒããæŽæ°ããå¿ èŠããããŸãã
-
enum ã§ã¯ããªã¢ã³ãããšã®åå²ãå¿ èŠã§ãããsealed trait ã§ã¯ã³ã³ãã€ã©ã ååã«å¯ŸããŠåçžåããã颿°ãæå®ã§ããŸãã
-
enum ã«ããã·ãŒãªã³ã°
// Copyright 2025 Google LLC // SPDX-License-Identifier: Apache-2.0 use std::collections::BTreeMap; pub enum GetSource { WebUrl(String), BytesMap(BTreeMap<String, Vec<u8>>), } impl GetSource { fn get(&self, url: &str) -> Option<&Vec<u8>> { match self { Self::WebUrl(source) => unimplemented!(), Self::BytesMap(map) => map.get(url), } } }
-
åæ©: API ã¯ãããã«å¯ŸããŠæå¹ãªåã®ç¹å®ã®äžèЧãåæãšããŠèšèšãããŠããã API ã®å©çšè ããããæ¡åŒµããããšã¯æ³å®ãããŠããŸããã
-
Rust ã® enum 㯠代æ°çããŒã¿å ã§ãããåããªã¢ã³ãããšã«ç°ãªãæ§é ã å®çŸ©ã§ããŸãã
åéã«ãã£ãŠã¯ãããã§åé¡ã«å¯ŸããŠååãªå€æ æ§ã«ãªãå ŽåããããŸãã å®éã«è©ŠããäœãããŸãæ©èœããããã©ã®è§£æ±ºçãããçã«ããªã£ãŠãããã 確ãããŠãã ããã
-
API ã®ãŠãŒã¶ãŒåãéšåã§ enum ãåç §ããããã«ãããšããŠãŒã¶ãŒã¯ã©ã®åã æå¹ãªå ¥åãªã®ããææ¡ã§ããçšæãããã¡ãœããã䜿ã£ãŠãããã®åã æ§ç¯ã§ããŸãã
-
enum ãæ§æããåã« API ãå éšçã«ç¶æããäžå€æ¡ä»¶ããããã〠ãŠãŒã¶ãŒããããã®åãæ§ç¯ã§ããå¯äžã®æ¹æ³ãããã®äžå€æ¡ä»¶ãæ§ç¯ããŠ ç¶æããã³ã³ã¹ãã©ã¯ã¿ãŒãéãããšã ãã§ãããªãããžã§ããªãã¯ã¡ãœãããžã® å ¥åããã®äžå€æ¡ä»¶ãæºãããŠãããšç¢ºä¿¡ã§ããŸãã
-
äžæ¹ã§ãenum ãæ§æããåããŠãŒã¶ãŒãèªç±ã«æ§ç¯ã§ããåã§ããå Žåã¯ã ãµãã¿ã€ãºãè§£éãèæ ®ããå¿ èŠããããããããŸããã
-
ãŠãŒã¶ãŒãæ¡åŒµã§ããå€çžæ§ã®ããã®ãã¬ã€ã
// Copyright 2025 Google LLC // SPDX-License-Identifier: Apache-2.0 // ã¯ã¬ãŒã A pub trait Trait { fn use_trait(&self) {} } // ã¯ã¬ãŒã BãA ã«äŸå pub struct Data(u8); impl Trait for Data {} fn main() { let data = Data(7u8); data.use_trait(); }
- éåžžã®ãã¬ã€ãã«ã€ããŠã¯ãã§ã«è©³ãã説æããŸããããenum ã sealed trait ãšæ¯ã¹ããšããã¬ã€ãã§ã¯ API ããŠãŒã¶ãŒã«æ±ããæ¯ãèãã å®è£ ããããšã§ããŠãŒã¶ãŒã API ãæ¡åŒµã§ããŸãã
ãã®ãŠãŒã¶ãŒã«ããæ¡åŒµèœåã¯ãã·ãªã¢ã©ã€ãºãã ããŒããŠã§ã¢ã®æœè±¡è¡šçŸãåå®å šãªç·åœ¢ä»£æ°ã«è³ããŸã§ã å€ãã®åéã§åŒ·åã§ãã
- ãã¬ã€ããã¯ã¬ãŒãã§å ¬éãããŠããã°ããã®ã¯ã¬ãŒãã«äŸåãããŠãŒã¶ãŒã¯ã èªåã§å®çŸ©ããåã«å¯ŸããŠãã®ãã¬ã€ããå®è£ ã§ããŸãã
åé¡è§£æ±º: åé¡ãåè§£ãã
// èäœæš© 2025 Google LLC // SPDX-License-Identifier: Apache-2.0 // åé¡: GUI API ãå®è£ ãã // åã: æç» API ã«ãšã£ãŠæçšãªæå°éã®æ¯ãèãã¯äœã§ããããïŒ pub trait DrawApi { fn arc(&self, center: [f32; 2], radius: f32, start_angle: f32, end_angle: f32); fn line(&self, start: [f32; 2], end: [f32; 2]); } pub struct TextDraw; impl DrawApi for TextDraw { fn arc(&self, center: [f32; 2], radius: f32, start_angle: f32, end_angle: f32) { println!("arc of radius ") } fn line(&self, start: [f32; 2], end: [f32; 2]) { /* ... */ } } // åã: ãŠãŒã¶ãŒã«ãšã£ãŠè¯ã API ãšã¯äœã§ããããïŒ pub trait Draw { fn draw<T: DrawApi>(&self, surface: &mut T); } pub struct Rect { start: [f32; 2], end: [f32; 2], } impl Draw for Rect { fn draw<T: DrawApi>(&self, surface: &mut T) { surface.line([self.start[0], self.start[1]], [self.end[0], self.start[1]]); surface.line([self.end[0], self.start[1]], [self.end[0], self.end[1]]); surface.line([self.end[0], self.end[1]], [self.start[0], self.end[1]]); surface.line([self.start[0], self.end[1]], [self.start[0], self.start[1]]); } }
- åé¡ãåè§£ããããšã«ã¯ãã§ã«é·ããŠããã¯ãã§ããããããã OOP ã¹ã¿ã€ã«ã®ææ³ã«æ £ããŠããã§ãããã
ããã¯å€§ããªå€åã§ã¯ãªããç©äºãžã®ã¢ãããŒãã®é åºãå ¥ãæ¿ããå¿ èŠããã ã ãã§ãã
-
ãŸãã¯ãžã§ããªã¯ã¹ãšãã¬ã€ãããŸã㯠enum ã®ããããã§åé¡ãè§£ããŠã¿ãŸãããã
åé¡ã«ç¹å®ã®åã®éåãå¿ èŠã§ããïŒ ãã®å Žåããã®åé¡ãè§£ãæãã¯ãªãŒã³ãª æ¹æ³ã¯ enum ãããããŸããã
åé¡ã¯æ¬åœã«é¢äžããåã®è©³çŽ°ãæ°ã«ããŠããŸããããããšã æ¯ãèãã«æ³šç®ã§ããŸããïŒ
-
äœããå®è£ ããããã®å®çšæå°éã®ç¥èãèŠã€ããããšã軞㫠åé¡è§£æ±ºãçµã¿ç«ãŠãŸãããã
ãã®ãŠãŒã¹ã±ãŒã¹ã«å¯ŸããŠããã§ã«ãã¬ã€ãã¯ååšããŸããïŒ ãããªããããã䜿ããŸãããïŒ
-
æ¬åœã«ç°çš®ã³ã¬ã¯ã·ã§ã³ãå¿ èŠãªãã䜿ããŸãããïŒ Rust ã«ãããååšããã®ã«ã¯ çç±ããããŸãã
XY åé¡ã«æ³šæããŠãã ãã: ããåé¡ã¯ 1 ã€ã®è§£æ±ºçã§æãç°¡åã«å¯ŸåŠã§ãã ããã«èŠãããããããŸããããããã§ã¯æ ¹æ¬åå ã«å¯ŸåŠã§ãããæ°ã㪠é£ããåé¡ãå°æ¥çŸããåå ã«ãªããããããŸããã
ã€ãŸãããã¬ã€ããªããžã§ã¯ãã«ããåçãã£ã¹ããããæ¬åœã«å¿ èŠãªãã®ã 㚠確信ããŠãããããã䜿ããšæ±ºããŠãã ããã
ãã¬ã€ããæ¬åœã«å¿ èŠãªãã®ã ãšç¢ºä¿¡ããŠãããããã䜿ããšæ±ºããŠãã ããã
éèŠ: ãã®ã¢ãžã¥ãŒã«ã¯éçºã®åææ®µéã«ãããŸã
Comprehensive Rust ã®ãã®ã¢ãžã¥ãŒã«ã¯ããŸã 宿ããŠãããšã¯èããªãã§ãã ããã
ãã®ç¹ãèžãŸããããã§ããã£ãŒãããã¯ãã³ã¡ã³ãããããŠç¹ã«æžå¿µç¹ããã²ãå¯ããã ããããã®ã¢ãžã¥ãŒã«ã®éçºã«ã€ããŠã³ã¡ã³ãããã«ã¯ã GitHub issue tracker ã䜿çšããŠãã ããã
Unsafe Rust Deep Dive ãžãããã
ãã® deep dive ã¯ãUnsafe Rust ãçç£çã«æ±ããããã«ãªãããšãç®çãšããŠããŸãã
ããã§ã¯ã次㮠3 ã€ã®é åã«åãçµã¿ãŸãã
- Unsafe Rust ã®ã¡ã³ã¿ã«ã¢ãã«ã確ç«ãã
- Unsafe Rust ã®èªã¿æžããç·Žç¿ãã
- Unsafe Rust ã®ã³ãŒãã¬ãã¥ãŒãç·Žç¿ãã
ãã®ã¯ã©ã¹ã®ç®æšã¯ãç°¡åãªã±ãŒã¹ã§ããã°èªåã§ã¬ãã¥ãŒã§ããã ãã® Unsafe Rust ãåŠã³ãããçµéšè±å¯ãª Unsafe Rust ãšã³ãžãã¢ã«ããã¬ãã¥ãŒãå¿ èŠãªé£ããã±ãŒã¹ãèŠåããããããã«ãªãããšã§ãã
-
Unsafe Rust ã®ã¡ã³ã¿ã«ã¢ãã«ã確ç«ãã
unsafeããŒã¯ãŒãã®æå³- å®å šæ§ã«ã€ããŠè©±ãããã®å ±éã®èªåœ
- ã¡ã¢ãªãã©ã®ããã«åäœãããã«ã€ããŠã®ã¡ã³ã¿ã«ã¢ãã«
- äžè¬çãªãã¿ãŒã³
unsafeã䜿çšããã³ãŒãã«å¯ŸããæåŸ äºé
-
unsafe ãæ±ãç·Žç¿ããã
- ã³ãŒããšããã¥ã¡ã³ãã®äž¡æ¹ãèªãããšãšæžãããš
- unsafe API ã䜿ãããš
- ããããèšèšãå®è£ ããããš
-
ã³ãŒããã¬ãã¥ãŒãã
- ç°¡åãªã±ãŒã¹ãèªåã§ã¬ãã¥ãŒã§ããèªä¿¡
- é£ããã±ãŒã¹ãæ€åºããããã®ç¥è
ãããã§ã¯ãã¹ãã€ã©ã«åã®æææ³ã䜿ããŸããããã¯ãåããããã¯ãæ·±ããå¢ããªããäœåºŠãåãäžãããšããæå³ã§ããã
ç¹ã«ã¯ã©ã¹ã®åå è å士ããäºããããç¥ããªãå Žåã¯ãèªå·±ç޹ä»ã®æéãèšãããšæçã§ããåèªã«èªå·±ç޹ä»ããŠãããããã®ã¯ã©ã¹ã«å¯Ÿããç¹å¥ãªç®æšãããã°æžãçããŠãããŸãããã
- ããªãã¯èª°ã§ããïŒ
- äœã«åãçµãã§ããŸããïŒ
- ãã®ã¯ã©ã¹ã§ã®ç®æšã¯äœã§ããïŒ
ã»ããã¢ãã
ããŒã«ã«ã® Rust ã€ã³ã¹ããŒã«
èšèªã® 2024 ãšãã£ã·ã§ã³ããµããŒããã Rust ã³ã³ãã€ã©ãã€ã³ã¹ããŒã«ããŠããå¿ èŠããããŸããããã¯ã1.84 ããæ°ããä»»æã®ããŒãžã§ã³ã® rustc ã§ãã
$ rustc --version
rustc 1.87
ïŒä»»æïŒã³ãŒã¹ã®ããŒã«ã«ã€ã³ã¹ã¿ã³ã¹ãäœæãã
$ git clone --depth=1 https://github.com/google/comprehensive-rust.git
Cloning into 'comprehensive-rust'...
...
$ cd comprehensive-rust
$ cargo install-tools
...
$ cargo serve # ãã®åŸããã©ãŠã¶ã§ http://127.0.0.1:3000/ ãéã
å
šå¡ã«ã1.87 ããæ°ããããŒãžã§ã³ã® rustc ãå®è¡ã§ããããšã確èªããŠããã£ãŠãã ããã
ã§ããªã人ã«ã¯ãäŒæ©äžã«ããã解決ãããšäŒããŠãã ããã
ã¯ããã«
ãã®ã³ãŒã¹ã§ã¯ãŸããUnsafe Rust ãšã¯äœãããã㊠unsafe ããŒã¯ãŒããäœãããã®ãã«ã€ããŠå
±éèªèãç¯ãããšããå§ããŸãã
æŠèŠ
segment outline
Unsafe Rust ã®å®çŸ©
ãUnsafe Rust 㯠Safe Rust ã®ã¹ãŒããŒã»ããã§ããã
ãUnsafe Rust ã§ã¯ãçãã€ã³ã¿ãããªãã¡ã¬ã³ã¹ãããã誀ã£ãŠåŒã³åºããš Rust ã®å®å šæ§ä¿èšŒãç Žãå¯èœæ§ããã颿°ãåŒã³åºãããã§ãããªã©ã远å ã®æ©èœã å ãããŸããã
ããããã®è¿œå æ©èœã¯ãunsafe æäœ ãšåŒã°ããŸããã
ãunsafe æäœã¯ãRust æšæºã©ã€ãã©ãªãæãç«ã€åºç€ãæäŸããŸããããšãã°ã çãã€ã³ã¿ãããªãã¡ã¬ã³ã¹ããæ©èœããªããã°ãVec ã Box ãå®è£
ãã ããšã¯äžå¯èœã§ããã
ãUnsafe Rust ãæžããŠããéããã³ã³ãã€ã©ã¯åŒãç¶ãæ¯æŽããŠãããŸããåçš ãã§ãã¯ãšåå®å šæ§ã¯äŸç¶ãšããŠé©çšãããŸããunsafe æäœã«ã¯ç¬èªã®ã«ãŒã«ã ããããã®ã¯ã©ã¹ã§ãããåŠã³ãŸããã
Rust Reference ã«ãã unsafe æäœïŒããã«ããŸãæéããããããªãã§ãã ããïŒ:
次ã®èšèªã¬ãã«ã®æ©èœã¯ãRust ã®å®å šãªãµãã»ããã§ã¯äœ¿çšã§ããŸãã:
- çãã€ã³ã¿ãããªãã¡ã¬ã³ã¹ããããšã
- å¯å€ãŸã㯠unsafe ãªå€éš static 倿°ãèªã¿æžãããããšã
- ä»£å ¥ããå Žåãé€ããunion ã®ãã£ãŒã«ãã«ã¢ã¯ã»ã¹ããããšã
unsafe颿°ãåŒã³åºãããšã- åãæ©èœãæå¹ã«ãã
<target_feature>屿§ãæããªã颿°ããã<target_feature>ãä»ããå®å šãªé¢æ°ãåŒã³åºãããšã- unsafe trait ãå®è£ ããããšã
- extern ãããã¯ã宣èšããããšã
- é ç®ã« unsafe 屿§ãé©çšããããšã
unsafe ããŒã¯ãŒããååšããçç±
- Rust ã¯å®å šæ§ãä¿èšŒããŸã
- ããããã³ã³ãã€ã©ã«ã§ããããšã«ã¯éçããããŸã
- unsafe ããŒã¯ãŒãã«ãããããã°ã©ããŒã¯ Rust ã® ã«ãŒã«ã«å¯Ÿãã責任ãè² ãããšãã§ããŸã
ãRust ã®æ ¹æ¬çãªç®æšã® 1 ã€ã¯ãã¡ã¢ãªå®å šæ§ã確ä¿ããããšã§ããã
ãããããéçããããŸããå®å šæ§ã«é¢ããèæ ®äºé ã®äžã«ã¯ãããã°ã©ãã³ã°èšèªã§ã¯è¡šçŸã§ããªããã®ã ãããŸããããšã衚çŸã§ãããšããŠããRust ã³ã³ãã€ã©ãå¶åŸ¡ã§ããããšã«ã¯ éçããããŸããã
ãunsafe ããŒã¯ãŒãã¯ãRust ã®ã«ãŒã«ãå®ã責任ã ã³ã³ãã€ã©ããããã°ã©ããŒãžç§»ããŸããã
ãunsafe ããŒã¯ãŒããç®ã«ãããšããããã¯è²¬ä»»ã ã³ã³ãã€ã©ããããã°ã©ããŒãžç§»ãããšãæå³ããŸãã
unsafe ããŒã¯ãŒãã«ã¯ 2 ã€ã®åœ¹å²ããããŸã
-
å®å šæ§ã«é¢ããé æ ®ãå¿ èŠãª API ã äœæãã
- unsafe 颿°:
unsafe fn get_unchecked(&self) { ... } - unsafe ãã¬ã€ã:
unsafe trait Send {}
- unsafe 颿°:
-
å®å šæ§ã«é¢ããé æ ®ãå¿ èŠãª API ã 䜿çšãã
- çµã¿èŸŒã¿ã® unsafe æŒç®åãåŒã³åºã:
unsafe { *ptr } - unsafe 颿°ãåŒã³åºã:
unsafe { x.get_unchecked() } - unsafe ãã¬ã€ããå®è£
ãã:
unsafe impl Send for Counter {}
- çµã¿èŸŒã¿ã® unsafe æŒç®åãåŒã³åºã:
2 ã€ã®åœ¹å²:
- å®å šæ§ã«é¢ããé æ ®ãå¿ èŠãª API ã äœæ ããäœã«é æ ®ããå¿ èŠããããã å®çŸ©ãã
- å®å šæ§ã«é¢ããé æ ®ãå¿ èŠãª API ã äœ¿çš ãããã®é æ ®ããªãããŠããããšã 確èªãã
å®å šæ§ã«é¢ããé æ ®ãå¿ èŠãª API ãäœæãã
ããŸããunsafe ããŒã¯ãŒãã䜿ããšãRust ã®å®å šæ§ä¿èšŒãç Žãå¯èœæ§ããã API ã äœæã§ããŸããå ·äœçã«ã¯ãunsafe 颿°ãš unsafe ãã¬ã€ããå®çŸ©ãããšãã«ã unsafe ããŒã¯ãŒãã䜿ãå¿ èŠããããŸãã
ããã®åœ¹å²ã§äœ¿ãå ŽåãAPI ã®å©çšè ã«å¯ŸããŠæ³šæãå¿ èŠã§ããããšãäŒããŠã㟠ããã
ãAPI ã®äœæè ã¯ãã©ã®ãããªæ³šæãå¿ èŠããäŒããã¹ãã§ããunsafe API ã¯ã å®å šæ§èŠä»¶ã«é¢ããããã¥ã¡ã³ãããªããã°äžå®å šã§ããåŒã³åºãåŽã¯ãå¿ èŠãªèŠ ä»¶ãæºãããŠããããšãç¥ãå¿ èŠããããŸãããããããæžãçããããŠããªãã ã°ãããã¯äžå¯èœã§ããã
å®å šæ§ã«é¢ããé æ ®ãå¿ èŠãª API ã䜿çšãã
ãunsafe ããŒã¯ãŒããããäžæ¹ã®åœ¹å²ãã€ãŸã API ã®äœ¿çšãæ ãã®ã¯ãäžãã£ãã® è¿ãã§äœ¿ããããšãã§ãã
ããã®åœ¹å²ã§äœ¿ãããå Žåãunsafe ããŒã¯ãŒãã¯ãäœè ãå¿ èŠãªæ³šæãæã£ãããš ãæå³ããŸããäœè ã¯ã³ãŒããå®å šã§ããããšãæ€èšŒããŠãããä»ã®äººã«å¯ŸããŠã ã®ä¿èšŒãäžããŠããŸããã
ãæãäžè¬çãªã®ã¯ unsafe ãããã¯ã§ããããã«ãããæåã®åœ¹å²ã䜿ã£ãŠå®çŸ© ããã unsafe 颿°ãåŒã³åºããŸãã
ãunsafe ãããã¯ã§ã¯ãraw ãã€ã³ã¿ãããªãã¡ã¬ã³ã¹ããããšã®ããã«ãã³ã³ã ã€ã©ã unsafe ã ãšèªèããŠããæäœãè¡ãããšãã§ããŸããã
ãunsafe ããŒã¯ãŒãã unsafe ãã¬ã€ãã®å®è£ ã«äœ¿ãããŠããã®ãç®ã«ããããšã ããã§ãããã
ãŠã©ãŒã ã¢ããã®äŸ
次ã瀺ãäŸ:
- unsafe ããã㯠(
unsafe { ... }) ã䜿çšããããš - unsafe 颿° (
unsafe fn) ãå®çŸ©ããããš - unsafe ãã¬ã€ãã å®è£
ããããš (
unsafe impl { ... }) - unsafe ãã¬ã€ã (
unsafe trait) ãå®çŸ©ããããš
unsafe ãããã¯ã䜿çšãã
// Copyright 2026 Google LLC
// SPDX-License-Identifier: Apache-2.0
fn main() {
let numbers = vec![0, 1, 2, 3, 4];
let i = numbers.len() / 2;
let x = *numbers.get_unchecked(i);
assert_eq!(i, x);
}
ã³ãŒããé ã«ç¢ºèªããŠãã ãããåè¬è ãããªãã¡ã¬ã³ã¹æŒç®åã«æ £ããŠããããšã確èªããŠãã ããã
ã³ãŒãã®ã³ã³ãã€ã«ã詊ã¿ãŠãã³ã³ãã€ã©ãšã©ãŒãçºçãããŠãã ããã
unsafe ãããã¯ã远å ããŸã:
// Copyright 2026 Google LLC // SPDX-License-Identifier: Apache-2.0 fn main() { let numbers = vec![0, 1, 2, 3, 4]; let i = numbers.len() / 2; let x = unsafe { *numbers.get_unchecked(i) }; assert_eq!(i, x); }
åè¬è ã«ã³ãŒãã¬ãã¥ãŒãä¿ããŠãã ãããåŠç¿è ãå®å šæ§ã³ã¡ã³ãã远å ããæ¹åãžå°ããŠãã ããã
å®å šæ§ã³ã¡ã³ãã远å ããŸã:
#![allow(unused)] fn main() { // Copyright 2026 Google LLC // SPDX-License-Identifier: Apache-2.0 // SAFETY: `i` 㯠0..numbers.len() ã®ç¯å²å ã§ãªããã°ãªããªã }
è§£çäŸ
// Copyright 2026 Google LLC // SPDX-License-Identifier: Apache-2.0 fn main() { let numbers = vec![0, 1, 2, 3, 4]; let i = numbers.len() / 2; let x = unsafe { *numbers.get_unchecked(i) }; assert_eq!(i, x); }
unsafe 颿°ã®å®çŸ©
// Copyright 2026 Google LLC // SPDX-License-Identifier: Apache-2.0 /// null ã«ãªããããã€ã³ã¿ãåç §ã«å€æããŸãã /// /// `p` ã null ã®å Žå㯠`None` ãè¿ããããã§ãªãå Žå㯠`val` ã `Some` ã§ã©ããããŠè¿ããŸãã fn ptr_to_ref<'a, T>(ptr: *mut T) -> Option<&'a mut T> { if ptr.is_null() { None } else { // SAFETY: `ptr` 㯠null ã§ã¯ãªã unsafe { Some(&mut *ptr) } } }
ãããã¯å®å šãªã³ãŒãã®ããã«èŠããŸãããå®éã«ã¯ unsafe ãããã¯ãå¿ èŠã§ããã
éåç
§æäœãã€ãŸã unsafe ãããã¯å
ã® *p ã匷調ããŠãã ããã
ãåŒã³åºãåŽã¯ãptr ã null ã§ãããããŸãã¯åç
§ã«å€æã§ãã ããšãä¿èšŒããªããã°ãªããŸããã
ãçŽæã«åãããããããŸããããå€ãã®ãã€ã³ã¿ã¯åç §ã«å€æã§ã ãŸããã
ãããšãã°ãæå¹ãªå€ã§ã¯ãªãä»»æã®ãããåãæããã€ã³ã¿ãäœãã ãå¯èœæ§ããããŸãããã㯠Rust ã蚱容ããªãããšã§ããããã®é¢æ° ã¯ãã®ãããªäºæ ããèªèº«ãå®ãå¿ èŠããããŸãã
ããã®ãããAPI èšèšè ãšããŠã¯ 2 ã€ã®éããããŸããç¡å¹ãªå ¥åã é²ã責任ãèªåãã¡ã§è² ãããã«ããããunsafe ããŒã¯ãŒãã«ãã£ãŠ ãã®è²¬ä»»ãåŒã³åºãåŽã«ç§»ããã§ããã
ã1 ã€ç®ã®éã¯å°é£ã§ããåãå ¥ããŠããã®ã¯ãžã§ããªãã¯å Tãã€ãŸã Sized ãå®è£ ããããããåã ããã§ããããã¯éåžžã«å€ãã®åã§ãïŒ
ããããã£ãŠã2 ã€ç®ã®éã®ã»ããçã«ããªã£ãŠããŸãã
远å ã³ã³ãã³ãïŒæéãããã°ïŒ
ãã¡ãªã¿ã«ããã€ã³ã¿ã®è©³çްããããããåç §ã«å€æããéã®ã«ãŒã«ã« èå³ããããªããæšæºã©ã€ãã©ãªã«ã¯æçšãªããã¥ã¡ã³ãããããã ãããŸããããã«ãstd::pointer ã«ããå€ãã®ã¡ãœããã®ãœãŒã¹ã³ãŒã ã確èªãããšããã§ãããã
ãããšãã°ããã®ã¹ã©ã€ãã® ptr_to_ref 颿°ã¯ãå®éã«ã¯æšæº ã©ã€ãã©ãªã§ãã€ã³ã¿ã® as_mut ã¡ãœãããšããŠååšããŸããã
std::pointer.as_mut ã®ããã¥ã¡ã³ããéããŠãSafety ã»ã¯ã·ã§ã³ã匷調ããŠãã ããã
unsafe ãã¬ã€ããå®è£ ãã
// Copyright 2026 Google LLC
// SPDX-License-Identifier: Apache-2.0
pub struct LogicalClock {
inner: std::sync::Arc<std::sync::atomic::AtomicUsize>,
}
// ...
impl Send for LogicalClock {}
impl Sync for LogicalClock {}
ãã³ãŒããèŠãåã«ãå šå¡ããã¬ã€ããšã¯äœããç¥ã£ãŠããããããäžåºŠç¢ºèªããŠãããŸããããã¯ã©ã¹ã®ã»ãã®ã¿ãªããã«åããŠããã¬ã€ãã説æã§ãã人ã¯ããŸããã
- ããã¬ã€ãã¯ãå ±æã®æ¯ãèããäœãæ¹æ³ãšããŠèª¬æãããããšããããããŸãããã¬ã€ããå ±æã®æ¯ãèããšããŠæãããšãã¡ãœããã®æ§æããã®ã·ã°ããã£ã«æ³šç®ããããšã«ãªããŸãã
- ããã¬ã€ãã«ã¯ãããã«æ·±ãæãæ¹ããããŸããèŠä»¶ã®éåãšããŠæããæ¹æ³ã§ããããã¯ãå®è£ ããåã«å ±éããã»ãã³ãã£ã¯ã¹ã匷調ããŸãã
ãSend ãã¬ã€ããš Sync ãã¬ã€ããäœãã説æã§ãã人ã¯ããŸããã
- ããªãå Žå
- ã
SendãšSyncã¯äžŠè¡æ§ã«é¢ä¿ããŸãã现ããªç¹ã¯ãããããããŸããã倧ãŸãã«èšããšãSendåã¯å€ãšããŠã¹ã¬ããéã§å ±æã§ããŸããSyncåã¯åç §ã«ãã£ãŠå ±æãããªããã°ãªããŸããã - ããŒã¿ãã¹ã¬ããå¢çãè¶ããŠå®å šã«å ±æããã«ã¯ãåŸãã¹ãã«ãŒã«ããããããããŸããããããã«ãŒã«ã¯ã³ã³ãã€ã©ã§ã¯æ€æ»ã§ããªããããããããå®ã責任ã¯ã³ãŒãã®äœè ãè² ããªããã°ãªããŸããã
Arcã¯SendãšSyncãå®è£ ããŠããããããã®ã¯ããã¯ãåæ§ã«å®å šã§ãã_atomic_ãšããèªã¯ãçŸä»£è±èªã«ããããå°ããªç²åããšããæå³ã§ã¯ãªããå€ä»£ã®ãªã·ã£èªã«ç±æ¥ãããäžå¯åãããå šäœããšããæå³ãæã€ããšãææãããšåœ¹ã«ç«ã€ãããããŸããã
- ã
unsafe ãã¬ã€ããå®çŸ©ãã
// Copyright 2026 Google LLC // SPDX-License-Identifier: Apache-2.0 /// ãã®åã 32 ãããã®ã¡ã¢ãªã䜿çšããããšã瀺ããŸãã pub trait Size32 {}
ãã§ã¯ãèªåãã¡ç¬èªã® unsafe ãã¬ã€ããå®çŸ©ããŠã¿ãŸããããã
unsafe ããŒã¯ãŒãã远å ããã³ãŒããã³ã³ãã€ã«ããŠãã ããã
ããã¬ã€ãã®èŠä»¶ãæå³çãªãã®ã§ããå Žåããã®ãã¬ã€ãã«ã¯ ã¡ãœããããŸã£ããäžèŠãªããšããããŸãããã ããããã¥ã¡ã³ãã¯äžå¯æ¬ ã§ããã
ãã¡ãœãããæããªããã¬ã€ãã¯ããŒã«ãŒãã¬ã€ããšåŒã°ããŸãããããã åã«å¯ŸããŠå®è£ ãããšããåã·ã¹ãã ã«æ å ±ã远å ããŠããããšã«ãªããŸãã ããã«ããã³ã³ãã€ã©ã¯ãããã¥ã¡ã³ãã«èšè¿°ãããèŠä»¶ãæºããåã« ã€ããŠæ±ããããã«ãªããŸããã
unsafe ã®ç¹æ§
unsafe ã¯å±éºã§ã
ãUse-after-freeïŒUAFïŒãæŽæ°ãªãŒããŒãããŒãå¢çå€ïŒOOBïŒã®èªã¿åã/æžã蟌ã¿ã¯ã è匱æ§ã® 90% ãå ããŠããããã®äžã§æãäžè¬çãªã®ã¯ OOB ã§ããã
â Jeff Vander Stoep ãš Chong ZangãGoogleã âQueue the Hardening Enhancementsâ
ããœãããŠã§ã¢æ¥çã¯ãunsafe ã³ãŒããæ£ããæžãããšãé£ãããéåžžã«æ·±å»ãªåé¡ãåŒãèµ·ããããšãç€ºãæ°å€ãã®èšŒæ ãèç©ããŠããŸãããã
ããã®ãªã¹ãã®åé¡ã¯ Rust ã«ãã£ãŠæé€ãããŸããunsafe ããŒã¯ãŒãã¯ãããããããªãã®ãœãŒã¹ã³ãŒãã«åã³æã¡èŸŒã¿ãŸããã
ãæ³šæããŠãã ãããã
unsafe ã¯å¿ èŠã«ãªãããšããããŸã
Rust ã³ã³ãã€ã©ã¯ãèªèº«ãã³ã³ãã€ã«ããã³ãŒãã«å¯ŸããŠããããã®ã«ãŒã«ãé©çšã§ããŸããã
// Copyright 2026 Google LLC
// SPDX-License-Identifier: Apache-2.0
fn main() {
let pid = unsafe { libc::getpid() };
println!("{pid}");
}
ãunsafe ã å¿ èŠãšãã æäœããããŸãã
ãRust ã³ã³ãã€ã©ã¯ãå€éšé¢æ°ã Rust ã® ã¡ã¢ãªä¿èšŒã«åŸã£ãŠããããšãæ€èšŒã§ããŸããããããã£ãŠãå€éšé¢æ°ã®åŒã³åºãã«ã¯ unsafe ãããã¯ãå¿ èŠã§ããã
ä»»æ:
ãå€éšç°å¢ãšã®ããåãã§ã¯ããã°ãã°ã¡ã¢ãªã®å ±æã䌎ããŸããã³ã³ãã¥ãŒã¿ãŒãæäŸãã ã€ã³ã¿ãŒãã§ãŒã¹ã¯ã¡ã¢ãªã¢ãã¬ã¹ïŒãã€ã³ã¿ïŒã§ããã
ãããã¯ãLinux ã«ãŒãã«ã«ãç§ãã¡ã管çããã¡ã¢ãªãžæžã蟌ãããæ±ããäŸã§ã:
// Copyright 2026 Google LLC
// SPDX-License-Identifier: Apache-2.0
fn main() {
let mut buf = [0u8; 8];
let ptr = buf.as_mut_ptr() as *mut libc::c_void;
let status = unsafe { libc::getrandom(ptr, buf.len(), 0) };
if status > 0 {
println!("{buf:?}");
}
}
ããã® FFI åŒã³åºãã¯ããªãã¬ãŒãã£ã³ã°ã·ã¹ãã ã«åããããŠãç§ãã¡ã®ãããã¡ãŒ (buf) ã åããŸããå€éšé¢æ°ãåŒã³åºãããšã«å ããŠãOS ããã®ã¡ã¢ãªã«ã©ã®ããã«ã¢ã¯ã»ã¹ãããã ã³ã³ãã€ã©ãæ€èšŒã§ããªãããããã®å¢çã unsafe ãšããŠæç€ºããªããã°ãªããŸãããã
Unsafe ã¯ãšãã©ãæçšã§ã
ã³ãŒããããé«éã«ã§ããŸãïŒ
// Copyright 2026 Google LLC // SPDX-License-Identifier: Apache-2.0 fn iter_sum(xs: &[u64]) -> u64 { xs.iter().sum() } fn fast_sum(xs: &[u64]) -> u64 { let mut acc = 0; let mut i = 0; unsafe { while i < xs.len() { acc += *xs.get_unchecked(i); i += 1; } } acc } fn main() { let data: Vec<_> = (0..1_000_000).collect(); let baseline = iter_sum(&data); let unchecked = fast_sum(&data); assert_eq!(baseline, unchecked); }
unsafe ã䜿ã£ãã³ãŒãã¯ãããé«éã«ãªã ãããããŸããã
fast_sum() ã¯å¢çãã§ãã¯ãçç¥ããŸãããã ããæ§èœã«é¢ããäž»åŒµãæ€èšŒããã«ã¯ ãã³ãããŒã¯ãå¿
èŠã§ãããã®ãããªã±ãŒã¹ã§ã¯ãRust ã®ã€ãã¬ãŒã¿ã§ãé垞㯠å¢çãã§ãã¯ãçç¥ã§ããŸãã
ãªãã·ã§ã³: 2 ã€ã®é¢æ°ã«ã€ããŠçæãããã¢ã»ã³ããªãåäžã§ããããšã衚瀺ããŸãã
unsafeããŒã¯ãŒãã¯è²¬ä»»ãç§»ã
| ã¡ã¢ãªå®å šã | ã¡ã¢ãªå®å šæ§ã®è²¬ä»» | |
|---|---|---|
| Safe Rust | ã¯ã | ã³ã³ãã€ã© |
| Unsafe Rust | ã¯ã | ããã°ã©ã㌠|
ã¡ã¢ãªå®å šæ§ã«è²¬ä»»ãæã€ã®ã¯èª°ã§ããïŒ
- Safe Rust â ã³ã³ãã€ã©
- Unsafe Rust â ããã°ã©ããŒ
âsafe RustãæžããŠããéã¯ãã¡ã¢ãªå®å šæ§ã®åé¡ãåŒãèµ·ããããšã¯ã§ããŸãããã³ã³ãã€ã© ã¯ã誀ãã®ããããã°ã©ã ããã«ããããªãããšãä¿èšŒããŸããâ
âunsafeããŒã¯ãŒãã¯ãã¡ã¢ãªå®å
šæ§ãç¶æãã責任ãã³ã³ãã€ã©ãã ããã°ã©ããŒãžç§»ããŸããããã¯ãæºãããªããã°ãªããªãåææ¡ä»¶ãããããšã 瀺ããŠããŸãã
âãã®è²¬ä»»ãæããããã«ãããã°ã©ããŒã¯ããã®åææ¡ä»¶ãäœã§ããããçè§£ãã èªåã®ã³ãŒããåžžã«ãããæºããããšãä¿èšŒããªããã°ãªããŸããã
âãã®ã³ãŒã¹å šäœãéããŠããã®ç¶æ³ã衚ãããã« å®å šæ§ã®åææ¡ä»¶ ãšããçšèªã䜿ããŸããâ
ã¯ãŒã¯ãããŒãžã®åœ±é¿
ã³ãŒããæžãé
- ãããã
unsafe颿°/ãã¬ã€ãã®åææ¡ä»¶ãçè§£ããŠããããšã確èªãã - åææ¡ä»¶ãæºããããŠããããšã確èªãã
- safetyã³ã¡ã³ãã«èªåã®æ ¹æ ãèšé²ãã
ã³ãŒãã¬ãã¥ãŒã®åŒ·å
- èªå·±ã¬ãã¥ãŒ â ãã¢ã¬ãã¥ã¢ãŒ â unsafe Rust ã®å°éå®¶ïŒå¿ èŠã«å¿ããŠïŒ
- ã³ãŒããšãã®æ ¹æ ãååã«çè§£ã§ãã人ã«ãšã¹ã«ã¬ãŒã·ã§ã³ãã
ãunsafe ããŒã¯ãŒãã¯ããã°ã©ããŒã«ãã倧ããªè²¬ä»»ã課ãããããã£ãŠã ãã匷åºãªéçºã¯ãŒã¯ãããŒãå¿ èŠã«ãªãã
ããã®ã¯ã©ã¹ã§ã¯ãã³ãŒãã¬ãã¥ãŒãå¿ é ã§ãããäœæè ãšäž»ã¬ãã¥ã¢ãŒã unsafe Rust ã®å°éå®¶ã«ã¢ã¯ã»ã¹ã§ãããç¹å®ã®ãœãããŠã§ã¢éçºã¯ãŒã¯ãããŒãåæãšããŠãããã
ãäœæè ãšäž»ã¬ãã¥ã¢ãŒã¯ãåçŽãª unsafe Rust ã³ãŒãã¯èªåãã¡ã§æ€èšŒãã å¿ èŠãªå Žåã«ã¯ unsafe ã®å°éå®¶ã«å§ãããã
ãunsafe Rust ã®å°éå®¶ã¯ããå°æ°ãããããããããéåžžã«å€å¿ãªã®ã§ã ãã®æéãæé©ã«äœ¿ãå¿ èŠããããã
äŸ: may_overflow 颿°
// Copyright 2026 Google LLC // SPDX-License-Identifier: Apache-2.0 /// è² ã®æ°ã« 2^31 - 1 ãå ããŸãã unsafe fn may_overflow(a: i32) -> i32 { a + i32::MAX } fn main() { let x = unsafe { may_overflow(123) }; println!("{x}"); }
ãunsafe ããŒã¯ãŒãã¯ãäžéšã®äººãæ³å®ããŠãããã®ãšã¯åŸ®åŠã«ç°ãªãæå³ãæã€ããšããããŸããã
ãã³ãŒãã®äœè ã¯ããã®ã³ãŒããæ£ãããšèããŠããŸããååãšããŠããã®ã³ãŒãã¯å®å šã§ããã
ããã®ããã¡ãã®äŸã§ã¯ãmay_overflow 颿°ã¯è² ã®æ°ã«å¯ŸããŠã®ã¿åŒã³åºãããããšãæå³ããŠããŸããã
åŠç¿è
ã«ããªã may_overflow ã« unsafe ããŒã¯ãŒããå¿
èŠãªã®ã説æã§ãããå°ããŠãã ããã
ãäœãåé¡ãªã®ãããããããªãå Žåã¯ãããã§å°ãç«ã¡æ¢ãŸã£ãŠèª¬æããŸããããi32 ã§ã¯ãæ£ã®æ°ã«äœ¿ããã®ã¯ 31 ãããã ãã§ããæŒç®ã«ãã£ãŠ 31 ããããè¶
ããçµæãçæããããšãããã°ã©ã ã¯äžæ£ãªç¶æ
ã«çœ®ãããŸãããããŠãããã¯åãªãæ°å€äžã®åé¡ã§ã¯ãããŸãããã³ã³ãã€ã©ã¯ãäžæ£ãªç¶æ
ã¯èµ·ããããªããšããåæã§ã³ãŒããæé©åããŸãããã®çµæãã³ãŒããã¹ãåé€ãããå®è¡æã®æåãäžå®å®ã«ãªãã ãã§ãªããã»ãã¥ãªãã£è匱æ§ãå°å
¥ãããŸããã
ã³ãŒããã³ã³ãã€ã«ããŠå®è¡ããpanic ãçºçããããšã確èªããŠãã ãããæ¬¡ã«ãplayground ã§ãã®äŸã --release ã¢ãŒãã§å®è¡ããæªå®çŸ©åäœãåŒãèµ·ãããŠãã ããã
ããã®ã³ãŒãã¯æ£ãã䜿çšã§ããŸãããäžé©åãªäœ¿çšã¯éåžžã«å±éºã§ããã
ããããŠããã®äœ¿çšãæ£ããããšãã³ã³ãã€ã©ãæ€èšŒããã®ã¯äžå¯èœã§ããã
ããããunsafe ããŒã¯ãŒããã¡ã¢ãªå®å
šæ§ã®è²¬ä»»ãã³ã³ãã€ã©ããããã°ã©ããžç§»ãå Žæã瀺ãããšç§ãã¡ãèšããšãã®æå³ã§ãã
å®å šæ§ã®åææ¡ä»¶
å®å šæ§ã®åææ¡ä»¶ãšã¯ãããæäœãå®å šã«è¡ãããã«ããã®åã«æºããããŠããªããã°ãªããªã æ¡ä»¶ã§ãã
âå®å šæ§ã®åææ¡ä»¶ãšã¯ãRust ã®å®å šæ§ä¿èšŒãç¶æããããã«æºãããªããã°ãªããªã ã³ãŒãã«é¢ããæ¡ä»¶ã§ã
âå®å šæ§ã®åææ¡ä»¶ãš Safe Rust ã®ã«ãŒã«ãšã®éã«ã¯ã匷ãèŠªåæ§ããããšæããã§ããããâ
Q: ããã€ãæããããŸããïŒ
(ããå®å šãªãªã¹ãã¯æ¬¡ã®ã¹ã©ã€ãã«ãããŸã)
äžè¬çãªå®å šæ§ã®åææ¡ä»¶
- ãšã€ãªã¢ã·ã³ã°ãšå¯å€æ§
- ã¢ã©ã€ã³ã¡ã³ã
- é åã¢ã¯ã»ã¹ãå¢çå ã§ããããš
- åæå
- ã©ã€ãã¿ã€ã
- ãã€ã³ã¿ã®æ¥æŽ
- åŠ¥åœæ§
- ã¡ã¢ãª
ååææ¡ä»¶ã®èª¬æã«ããŸãæéããããããªãã§ãã ãããã³ãŒã¹ã®äžã§ 詳现ãèŠãŠããããšã«ãªããŸããæå³ã¯ããã®ãããªåææ¡ä»¶ã ããã€ãããããšã瀺ãããšã§ãã
ãäžå®å šãªãªã¹ãã§ãããèãå§ããããã®äž»èŠãªå®å šæ§ã®åææ¡ä»¶ã ããã€ãæããŠããŸããã
- åŠ¥åœæ§ãå€ã¯ãããã衚ãåã«ãšã£ãŠåŠ¥åœãªå€ã§ãªããã°ãªããŸãããRust ã® åç
§ã¯ null ã§ãã£ãŠã¯ãªããŸããã
unsafeã§ãããäœæãããšã - ã¢ã©ã€ã³ã¡ã³ããå€ãžã®åç §ã¯é©åã«ã¢ã©ã€ã³ãããŠããªããã°ãªãããããã¯
- ãšã€ãªã¢ã·ã³ã°ããã¹ãŠã® Rust ã³ãŒã㯠Rust ã®åçšèŠåãå®ããªããã°ãªããŸããããã€ã³ã¿ãã å¯å€åç
§ (
&mut T) ãæåã§äœæããŠããå Žåã¯ã äœæã§ããã®ã¯ 1 ã€ã ãã§ã - åæåãRust ã®åã®ãã¹ãŠã®ã€ã³ã¹ã¿ã³ã¹ã¯å®å šã«åæåãããŠããªããã°ãªããŸããã çã¡ã¢ãªããå€ãäœæããã«ã¯ãæžã蟌ãã§ããããšã確èªããå¿ èŠããã
- ãã€ã³ã¿ã®æ¥æŽããã€ã³ã¿ã®èµ·æºã¯éèŠã§ãã
usizeã çãã€ã³ã¿ã«ãã£ã¹ãããããšã¯ããã¯ãèš±å¯ãããŠããŸããã - ã©ã€ãã¿ã€ã ãåç §ã¯ããã®åç §å ããé·çãããŠã¯ãããŸããã
äžèŠãã以äžã«åŸ®åŠãªæ¡ä»¶ããããŸãã
ãå¢çå ã®é åã¢ã¯ã»ã¹ããèããŠã¿ãŸããããã¡ã¢ãªäœçœ®ããèªã¿åãããšãããªãã¡ ããªãã¡ã¬ã³ã¹ã¯ãããã°ã©ã ãå£ãããã«å¿ é ã§ã¯ãããŸãããå¢çå€ã® åç §ãäœæããæç¹ã§ããã§ã«ã³ã³ãã€ã©ã®åæãç Žãããäžå®å®ãª æåã«ã€ãªãããŸãã
Rust 㯠LLVM ã«ããã® getelementptr inbounds ã®åæã䜿ãããäŒããŸãããã®åæã¯ ã³ã³ãã€ã©å
ã®åŸç¶ã®æé©åãã¹ã誀ã£ãåäœã«å°ããŸãïŒå¢çå€ã® ã¡ã¢ãªã¢ã¯ã»ã¹ã¯èµ·ããããªãããã§ãïŒã
ä»»æ: 以äžã®ã³ãŒãã衚瀺ããã the playground ãéããŠãã ããããã㯠æ¬è³ªçã«ã¯ Rust æ§æã§æžããã C 颿°ã§ãé
åããèŠçŽ ãååŸãããã®ã 㚠説æããŠãã ãããShow LLVM IR ãã¿ã³ã§ LLVM IR ãçæããŸããæ¬¡ã 匷調衚瀺ããŠãã ããã getelementptr inbounds i32, ptr %array, i64 %offset.
// Copyright 2026 Google LLC
// SPDX-License-Identifier: Apache-2.0
#[unsafe(no_mangle)]
pub unsafe fn get(array: *const i32, offset: isize) -> i32 {
unsafe { *array.offset(offset) }
}
æåŸ
ãããåºåïŒåŒ·èª¿è¡šç€ºããè¡ã¯ %_3 ã§å§ãŸããŸãïŒ:
define noundef i32 @get(ptr noundef readonly captures(none) %array, i64 noundef %offset) unnamed_addr #0 {
start:
%_3 = getelementptr inbounds i32, ptr %array, i64 %offset
%_0 = load i32, ptr %_3, align 4, !noundef !3
ret i32 %_0
}
å¢ç: ããªãã¡ã¬ã³ã¹ããªããŠããLLVM ã® inbounds ã®åæã«ãããå¢çå€ã®ãã€ã³ã¿ïŒãæ«å°Ÿã® 1 ã€å ãã«ãŒã«ãè¶ ãããã®ïŒã äœæããããšã¯ UB ã«ãªããšãããªãã¯æ£ããææããŸããã
ã²ãã¿ãŒã®äŸ
// Copyright 2026 Google LLC // SPDX-License-Identifier: Apache-2.0 /// `arr` ãã `index` çªç®ã®èŠçŽ ãè¿ã unsafe fn get(arr: *const i32, index: usize) -> i32 { unsafe { *arr.add(index) } }
âå®å šæ§ã®äºåæ¡ä»¶ãšã¯ãRust ã®å®å šæ§ä¿èšŒãç¶æããããã«æºããããªããã°ãªããªã ã³ãŒãäžã®æ¡ä»¶ã§ã
âå®å šæ§ã®äºåæ¡ä»¶ãš Safe Rust ã®ã«ãŒã«ã®éã«ã¯ã坿¥ãªå¯Ÿå¿é¢ä¿ãããããšã«æ°ã¥ãã§ããããâ
質å: âget ã®å®å
šæ§ã®äºåæ¡ä»¶ã¯äœã§ããïŒâ
- ãã€ã³ã¿
arr㯠null ã§ã¯ãªããæ£ããã¢ã©ã€ã³ãããŠãããi32ã®é åãæããŠãã indexã¯ç¯å²å ã«ãã
å®å šæ§ã³ã¡ã³ãã远å ããŸã:
// Copyright 2026 Google LLC
// SPDX-License-Identifier: Apache-2.0
/// `arr` ãã `index` çªç®ã®èŠçŽ ãè¿ã
///
/// # Safety
///
/// - `arr` 㯠null ã§ã¯ãªããæ£ããã¢ã©ã€ã³ãããŠãããæå¹ãª `i32` ãæããŠãã
/// - `index` ã¯é
åã®ç¯å²å
ã«ãã
unsafe fn get(arr: *const i32, index: usize) -> i32 {
// SAFETY: åŒã³åºãå
ã index ãç¯å²å
ã§ããããšãä¿èšŒãã
unsafe { *arr.add(index) }
}
ä»»æ: ããã«å ç¢ã«ããããããããã°ãã«ãã§ã¯ã©ã³ã¿ã€ã ãã§ãã¯ã远å ã§ããŸãã
// Copyright 2026 Google LLC
// SPDX-License-Identifier: Apache-2.0
debug_assert!(!arr.is_null());
debug_assert_eq!(arr as usize % std::mem::align_of::<i32>(), 0);
æå³è«çåææ¡ä»¶
äŸ: u8 ãã bool ãž
äºåæ¡ä»¶ãç¹å®ãã
å®å šæ§ã®äºåæ¡ä»¶ã¯ã©ãã§èŠã€ããŸããïŒ
// Copyright 2026 Google LLC
// SPDX-License-Identifier: Apache-2.0
fn main() {
let b: *mut i32 = std::ptr::null_mut();
println!("{:?}", b.as_mut());
}
ããã°ã©ã ãã³ã³ãã€ã«ããŠãã³ã³ãã€ã©ãšã©ãŒïŒâerror[E0133]: call to unsafe function âŠâïŒãçºçãããŠãã ããã
質åããŸã: ã颿°ã®äºåæ¡ä»¶ãç¥ãããå Žåãã©ããèŠãŸããïŒ ããã§ã¯ãnull ãã€ã³ã¿ããå¯å€åç §ãžã®å€æããã€å®å šãªã®ããçè§£ããå¿ èŠã ãããŸããã
確èªããå Žæ:
- 颿°ã® API ããã¥ã¡ã³ããç¹ã«å®å šæ§ã»ã¯ã·ã§ã³
- ãœãŒã¹ã³ãŒããšãã®å éšã®å®å šæ§ã³ã¡ã³ã
- ã¢ãžã¥ãŒã«ããã¥ã¡ã³ã
- Rust Reference
as_mut ã¡ãœããã«ã€ããŠã¯ the documentation ãåç
§ããŠãã ããã
Safety ã»ã¯ã·ã§ã³ã匷調ããŸãã
Safety
ãã®ã¡ãœãããåŒã³åºããšãã¯ããã€ã³ã¿ã null ã§ãããã ãŸãã¯ãã®ãã€ã³ã¿ãåç §ã«å€æå¯èœã§ããããšãä¿èšŒããªããã°ãªããŸããã
ãconvertible to a referenceããã€ããŒãªã³ã¯ãã¯ãªãã¯ããŠããPointer to reference conversionãã«é²ã¿ãŸã
ãã€ã³ã¿ãåç §ã«å€æããããã®ã«ãŒã«ãã€ãŸãããã ãdereferenceableãã§ãããã©ãããçªãæ¢ããŸãã
ãã®æç²ïŒRust 1.90.0ïŒãRust ã®ãšã€ãªã¢ã·ã³ã°èŠåã匷å¶ããªããã°ãªããŸããã æ£ç¢ºãªãšã€ãªã¢ã·ã³ã°èŠåã¯ãŸã 決ãŸã£ãŠããŸãããâŠãã®å«æãèããŸãã
äŸ: åç §
// Copyright 2026 Google LLC
// SPDX-License-Identifier: Apache-2.0
fn main() {
let mut boxed = Box::new(123);
let a: *mut i32 = &mut *boxed as *mut i32;
let b: *mut i32 = std::ptr::null_mut();
println!("{:?}", *a);
println!("{:?}", b.as_mut());
}
æ§æã®çè§£ã確èªãã
-
Box<i32>åã¯ãbox ãææãããããŒãäžã®æŽæ°ãžã®åç §ã§ãã -
*mut i32åã¯ãããããæŽæ°ãžã®çãã€ã³ã¿ã§ããããã®æææš©ãã³ã³ãã€ã©ã¯ ææ¡ããŠããŸãããããã°ã©ããŒã¯ãã³ã³ãã€ã©ã®å©ããªãã«ã«ãŒã«ãå®ãããããšã ä¿èšŒããå¿ èŠããããŸãã- 泚: çãã€ã³ã¿ã¯æææš©ã®æ å ±ã Rust ã«æäŸããŸããããã€ã³ã¿ã¯ãæå³çã«ã¯ ããŒã¿ãææããŠããããšããæå³çã«ã¯åçšããŠããããšããããŸããããã® æ å ±ã¯ããã°ã©ããŒã®é ã®äžã«ããååšããŸããã
-
&mut *boxed as *mut _åŒ:*boxed㯠âŠ&mut *boxed㯠âŠ- æåŸã«ã
as *mut i32ã¯ãã®åç §ããã€ã³ã¿ã«ãã£ã¹ãããŸãã
-
&mut i32ã®ãããªåç §ã¯ããã®åç §å ããåçšãããŸããããã Rust ã® æææš©ã·ã¹ãã ã§ãã
æææš©ã®çè§£ã確èªãã
-
ã³ãŒããé ã«è¿œã:
- (3 è¡ç®) box ãããªãã¡ã¬ã³ã¹ããŠ
123ãžã®çãã€ã³ã¿ãäœæããæ°ãã åç §ãäœã£ãŠããã®æ°ããåç §ããã€ã³ã¿ãšããŠãã£ã¹ãããŸãã - (4 è¡ç®) NULL å€ãæã€çãã€ã³ã¿ãäœæããŸã
- (7 è¡ç®)
.as_mut()ã§çãã€ã³ã¿ã Option ã«å€æããŸã
- (3 è¡ç®) box ãããªãã¡ã¬ã³ã¹ããŠ
-
Rust ã§ã¯ãã€ã³ã¿ã null ãåãåŸãããšã匷調ããïŒåç §ãšã¯ç°ãªããŸãïŒã
-
ã³ã³ãã€ã«ããŠãšã©ãŒã¡ãã»ãŒãžã確èªããã
-
è°è«ãã
- (6 è¡ç®)
println!("{:?}", *a);- å
é ã®
*ã¯çãã€ã³ã¿ãããªãã¡ã¬ã³ã¹ããŸãã - ããã¯æç€ºçãªæäœã§ããäžæ¹ãéåžžã®åç §ã§ã¯ãDeref ãã¬ã€ãã®ãããã§ ã»ãšãã©ã®å Žåã¯æé»ã«ããªãã¡ã¬ã³ã¹ãããŸãããã㯠âauto-derefâ ãš åŒã°ããŸãã
- çãã€ã³ã¿ã®ããªãã¡ã¬ã³ã¹ã¯ unsafe ãªæäœã§ãã
- unsafe ãããã¯ãå¿ èŠã§ãã
- å
é ã®
- (7 è¡ç®)
println!("{:?}", b.as_mut());as_mut()㯠unsafe 颿°ã§ãã- unsafe 颿°ãåŒã³åºãã«ã¯ unsafe ãããã¯ãå¿ èŠã§ãã
- (6 è¡ç®)
-
宿Œ: ã³ãŒããä¿®æ£ãïŒunsafe ãããã¯ã远å ãïŒãå床ã³ã³ãã€ã«ããŠã åäœããããã°ã©ã ã瀺ãã
-
宿Œ:
as *mut i32ãas *mut _ã«çœ®ãæããã³ã³ãã€ã«ã§ããããšã瀺ãã- ãã®ãã£ã¹ãã§ã¯ã察象ã®åãéšåçã«çç¥ã§ããŸããRust ã³ã³ãã€ã©ã¯ã ãã£ã¹ãå
ã
&mut i32ã§ããããšãç¥ã£ãŠããŸãããã®åç §åã倿ã§ãã ãã€ã³ã¿åã¯*mut i32ã® 1 ã€ã ãã§ãã
- ãã®ãã£ã¹ãã§ã¯ã察象ã®åãéšåçã«çç¥ã§ããŸããRust ã³ã³ãã€ã©ã¯ã ãã£ã¹ãå
ã
-
å®å šæ§ã³ã¡ã³ãã远å ãã:
- unsafe ã³ãŒãã¯ã責任ãã³ã³ãã€ã©ããããã°ã©ããŒãžç§»ãããšã瀺ãã ãšèª¬æããŸããã
- unsafe ã³ãŒããæžãéã«ããã®ç¹å¥ãªè²¬ä»»ã«ã€ããŠèæ ®ããããšãã©ãäŒãã ã®ã§ãããããå®å šæ§ã³ã¡ã³ãã§ãã
- å®å šæ§ã³ã¡ã³ãã¯ãunsafe ã³ãŒãããªãæ£ããã®ãã説æããŸãã
- å®å šæ§ã³ã¡ã³ãããªããã°ãunsafe ã³ãŒãã¯å®å šã§ã¯ãããŸããã
-
è°è«ãã: 1 ã€ã®å€§ã㪠unsafe ãããã¯ã䜿ããã2 ã€ã®å°ããªãããã¯ã 䜿ãã:
- è€æ°ã§ã¯ãªãã1 ã€ã® unsafe ãããã¯ã䜿ãããšãå¯èœã§ãã
- ãããã¯ãåãããšãå®å šæ§ã³ã¡ã³ããã§ããã ãå ·äœçã«ã§ããŸãã
æšå¥šãããè§£ç
// Copyright 2026 Google LLC // SPDX-License-Identifier: Apache-2.0 fn main() { let mut boxed = Box::new(123); let a: *mut i32 = &mut *boxed as *mut i32; let b: *mut i32 = std::ptr::null_mut(); // SAFETY: `a` 㯠i32 ãžã® null ã§ã¯ãªããã€ã³ã¿ã§ãããåæåæžã¿ã§ã // äŸç¶ãšããŠå²ãåœãŠãããŠããŸãã println!("{:?}", unsafe { *a }); // SAFETY: `b` 㯠null ãã€ã³ã¿ã§ããã`as_mut()` ã¯ããã `None` ã«å€æããŸãã println!("{:?}", unsafe { b.as_mut() }); }
ç¬èªã®åææ¡ä»¶ãå®çŸ©ãã
- ãŠãŒã¶ãŒå®çŸ©åã¯ãç¬èªã®å®å šæ§ã®åææ¡ä»¶ãæã€ããšãã§ããŸã
- åŸãããããã倿ããŠæºãããããã«ãããã¥ã¡ã³ããå«ããŠãã ãã
äŸ: ASCII å
// èäœæš© 2026 Google LLC // SPDX-License-Identifier: Apache-2.0 /// 7 ããã ASCII ã§ãšã³ã³ãŒããããŠããããšãä¿èšŒãããããã¹ãã pub struct Ascii<'a>(&'a mut [u8]); impl<'a> Ascii<'a> { pub fn new(bytes: &'a mut [u8]) -> Option<Self> { bytes.iter().all(|&b| b.is_ascii()).then(|| Ascii(bytes)) } /// ASCII ã®åŠ¥åœæ§ãæ€æ»ããã«ããã€ãã¹ã©ã€ã¹ããæ°ãã `Ascii` ã /// äœæããŸãã /// /// # å®å šæ§ /// /// é ASCII ãã€ããäžãããšæªå®çŸ©åäœã«ãªããŸãã pub unsafe fn new_unchecked(bytes: &'a mut [u8]) -> Self { Ascii(bytes) } }
âAscii åã¯ãã€ãã¹ã©ã€ã¹ãå
ãæå°éã®ã©ãããŒã§ããå
éšçã«ã¯ãäž¡è
㯠åã衚çŸãå
±æããŠããŸãããã ããAscii ã§ã¯æäžäœãããã 䜿çšããŠã¯ãªããŸãããâ
ä»»æ: ãªãªãŒã¹ãã«ãã«åœ±é¿ãäžããããšãªãããã¹ãäžã«äºåæ¡ä»¶ã debug_assert! ã§æ€èšŒã§ããããšãããã®äŸã« 远èšããŠãã ããã
// èäœæš© 2026 Google LLC
// SPDX-License-Identifier: Apache-2.0
unsafe fn new_unchecked(bytes: &mut [u8]) -> Self {
debug_assert!(bytes.iter().all(|&b| b.is_ascii()))
Ascii(bytes)
}
ã²ãŒã ã®ã«ãŒã«
ããã®è¬çŸ©ã§ã¯åé¡ã®ããã³ãŒãã®äŸãæ°å€ãèŠãŠããŸãããã äžè²«ããçšèªãäžè¶³ããŠããŸãã
ãæ¬¡ã®ã»ã¯ã·ã§ã³ã®ç®çã¯ããããŸã§èããŠããæŠå¿µã®å€ãã説æãã ããã€ãã®çšèªãå°å ¥ããããšã§ãã
- æªå®çŸ©åäœ
- å¥å š
- éå¥å š
ãå€ãã®å®å šæ§ã®åææ¡ä»¶ã¯æ§æçãšããããæå³è«çãªãã®ãªã®ã§ã å ±éã®èªåœã䜿ãããšãéèŠã§ããããããããšã§æå³è«ã«åæã§ããŸãã
ãå æ¬çãªç®æšã¯ãå¥å šæ§ãšã¯äœãã«ã€ããŠã®æèã®æ çµã¿ãç¯ãã unsafe ãå«ã Rust ã³ãŒããå¥å šãªãŸãŸã§ããããšã確ä¿ããããšã§ããã
Rust ã¯å¥å šã§ã
- å¥å šæ§ã¯ Rust ã®æ ¹å¹¹ã§ã
- å¥å šæ§ â ã¡ã¢ãªå®å šæ§ã®åé¡ãåŒãèµ·ããããšãäžå¯èœ
- å¥å šãªé¢æ°ã«ã¯å ±éã®ã圢ãããããŸã
âRust ã³ãŒãã®åºæ¬ååã¯ããããå¥å šã§ãããšããããšã§ãã
âãŸããªããå¥å šæ§ãšããçšèªã®æ£åŒãªå®çŸ©ã瀺ããŸãããããŸã§ã® ããã ã¯ãå¥å šãªã³ãŒããšã¯ãã¡ã¢ãªå®å šæ§ã®åé¡ãåŒãèµ·ãããªã ã³ãŒãã ãšèããŠãã ããã
âå¥å šãªã³ãŒãã¯ãå¥å šãªé¢æ° ãš å¥å šãªæäœ ã§æ§æãããŸãã
âå¥å šãªé¢æ°ãšã¯ãèããããã©ã®å ¥åãå¥å šæ§ã®åé¡ãåŒãèµ·ããããªã 颿°ã®ããšã§ãã
å¥å šãªé¢æ°ã«ã¯å ±éã®åœ¢ããããŸãã
ä»ããèŠãŠããã®ã¯ããã®åœ¢ã§ãã
âãŸã㯠Safe Rust ã§å®è£
ãããŠãããã®ããå§ãããã®åŸãããŸããŸãªéšåã« unsafe ãå°å
¥ãããšäœãèµ·ããããããèŠãŠãããŸãã
ã¡ã¢ãªã®ã³ã㌠- ã¯ããã«
// Copyright 2026 Google LLC
// SPDX-License-Identifier: Apache-2.0
/// `source` ãããã€ããèªã¿åãã`dest` ã«æžã蟌ã
pub fn copy(dest: &mut [u8], source: &[u8]) { ... }
ããããæåã®é¢æ°ãããã¿ã€ãã§ããã
ãcopy 㯠2 ã€ã®ã¹ã©ã€ã¹ãåŒæ°ãšããŠåãåããŸããdestïŒå®å
ïŒã¯å¯å€ã§ãããsource ã¯å¯å€ã§ã¯ãããŸãããã
ãå¥å šãª Rust ã³ãŒãã®åœ¢ãèŠãŠãããŸããããã
Safe Rust
// Copyright 2026 Google LLC // SPDX-License-Identifier: Apache-2.0 pub fn copy(dest: &mut [u8], source: &[u8]) { for (dest, src) in dest.iter_mut().zip(source) { *dest = *src; } } fn main() { let a = &[114, 117, 115, 116]; let b = &mut [82, 85, 83, 84]; println!("{}", String::from_utf8_lossy(b)); copy(b, a); println!("{}", String::from_utf8_lossy(b)); }
ããã®å®è£ ã§ã¯ Safe Rust ãã䜿çšããŠããŸããã
ããããäœãåããã§ããããïŒ
ãcopy ã¯ãSafe Rust ã§å®è£
ãããŠããéããã¡ã¢ãªå®å
šæ§ã®åé¡ãåŒãèµ·ãã ããšã¯äžå¯èœã§ããããã¯ãèãåŸããã¹ãŠã®å
¥ååŒæ°ã«å¯ŸããŠæãç«ã¡ãŸããã
ãããšãã°ãRust ã®ã€ãã¬ãŒã¿ã䜿ãããšã§ããã«ãã€ã³ã¿ãã§ãã¯ãå¢çãã§ã㯠ãå¿ èŠã«ãªããšãã£ãããã€ã³ã¿ãçŽæ¥æ±ãããšã«é¢ãããšã©ãŒã決ã㊠åŒãèµ·ãããªãããã«ã§ããŸããã
質å: ãã»ãã«äœãæãã€ããŸããïŒã
- ãšã€ãªã¢ã·ã³ã°ã®åé¡ã¯ãªã
- ãã³ã°ãªã³ã°ãã€ã³ã¿ã¯èµ·ããåŸãªã
- ã¢ã©ã€ã³ã¡ã³ãã¯æ£ãã
- åæåãããŠããªãã¡ã¢ãªã誀ã£ãŠèªã¿åãããšã¯ã§ããªã
ãRust ãå®å
šæ§ã®åææ¡ä»¶ããã¹ãŠæºããããããšãä¿èšŒããŠãããããcopy 颿°ã¯ å¥å
š ã ãšèšããŸããã
ãããã°ã©ãã®èгç¹ããã¯ããã®é¢æ°ã¯ Safe Rust ã§å®è£ ãããŠããããã å®å šæ§ã®åææ¡ä»¶ã¯ãªããã®ãšèããããŸããã
ããã ãããã㯠copy ãåžžã«åŒã³åºãåŽã®æãããšãè¡ããšããæå³ã§ã¯ ãããŸãããdest ã¹ã©ã€ã¹ã«å©çšå¯èœãªé åãååã§ãªãå ŽåãããŒã¿å
šäœã¯ ã³ããŒãããŸãããã
ã«ãã»ã«åããã Unsafe Rust
// Copyright 2026 Google LLC // SPDX-License-Identifier: Apache-2.0 pub fn copy(dest: &mut [u8], source: &[u8]) { let len = dest.len().min(source.len()); let mut i = 0; while i < len { // SAFETY: `i` 㯠source.len() ããåŸããããããå¢çå ã§ãªããã°ãªããŸãã let new = unsafe { source.get_unchecked(i) }; // SAFETY: `i` 㯠dest.len() ããåŸããããããå¢çå ã§ãªããã°ãªããŸãã let old = unsafe { dest.get_unchecked_mut(i) }; *old = *new; i += 1; } for (dest, src) in dest.iter_mut().zip(source) { *dest = *src; } } fn main() { let a = &[114, 117, 115, 116]; let b = &mut [82, 85, 83, 84]; println!("{}", String::from_utf8_lossy(b)); copy(b, a); println!("{}", String::from_utf8_lossy(b)); }
âããã§ã¯ãå éšã§äœ¿çšããã unsafe ãããã¯ãã«ãã»ã«åããå®å šãªé¢æ°ã ãããŸãã
âãã®å®è£ ã§ã¯ã€ãã¬ãŒã¿ãé¿ããŠããŸãã代ããã«ãå®è£ è ã ã¡ã¢ãªã«æåã§ã¢ã¯ã»ã¹ããŠããŸããâ
âããã¯æ£ããã§ããããïŒâ âäœãåé¡ã¯ããã§ããããïŒâ
âãã®æ£ãããä¿èšŒãã責任ãè² ãã®ã¯èª°ã§ããããïŒ é¢æ°ã®äœè ã§ãã
âunsafe ãããã¯ãå«ã Safe Rust 颿°ã¯ãå ¥åã«ãã£ãŠã¡ã¢ãªå®å šæ§ã®åé¡ã çºçãããªããªããäŸç¶ãšããŠå¥å šã§ãã
é²åºãã Unsafe Rust
// èäœæš© 2026 Google LLC // SPDX-License-Identifier: Apache-2.0 pub fn copy(dest: &mut [u8], source: *const u8) { let source = { let mut len = 0; let mut end = source; while unsafe { *end != 0 } { len += 1; end = unsafe { end.add(1) }; } unsafe { std::slice::from_raw_parts(source, len + 1) } }; for (dest, src) in dest.iter_mut().zip(source) { *dest = *src; } } fn main() { let a = [114, 117, 115, 116].as_ptr(); let b = &mut [82, 85, 83, 84, 0]; println!("{}", String::from_utf8_lossy(b)); copy(b, a); println!("{}", String::from_utf8_lossy(b)); }
ããå Žæããå¥ã®å Žæãžãã€ããã³ããŒãããšããæ©èœèªäœã¯åããŸãŸã§ãã
ããã ããã¹ã©ã€ã¹ãæåã§äœæããå¿ èŠããããŸãããã®ããã«ã¯ããŸã ããŒã¿ã®çµç«¯ãèŠã€ããå¿ èŠããããŸããã
ãä»åã¯ããã¹ããæ±ã£ãŠããã®ã§ãC ã®æ £ç¿ã§ãããã«çµç«¯ æååã䜿ããŸããã
ã³ãŒããã³ã³ãã€ã«ããŠãã ãããåºåãåããŸãŸã§ããããšã確èªããŠãã ããã
ãå¥å šã§ãªã颿°ã§ããå ¥åã«ãã£ãŠã¯æ£ããåäœããããšããããŸãããã¹ãã éããããšãã£ãŠããã®é¢æ°ãå¥å šã§ãããšã¯éããŸãããã
ãäœãåé¡ç¹ã«æ°ã¥ã人ã¯ããŸããïŒã
- å¯èªæ§: ã³ãŒãããã°ããèŠãŠææ¡ãã«ãã
sourceãã€ã³ã¿ã null ãããããªãsourceãã€ã³ã¿ããã³ã°ãªã³ã°ããŠãããããããªããã€ãŸããè§£æŸæžã¿ãŸãã¯æªåæåã® ã¡ã¢ãªãæããŠããå¯èœæ§ãããsourceããã«çµç«¯ãããŠããªããããããªã
ã颿°ã·ã°ããã£ã倿Žã§ããªããšä»®å®ããå Žåããããã®åé¡ã«å¯ŸåŠããããã« ã³ãŒããžã©ã®ãããªæ¹åãå ããããã§ããããïŒã
- null ãã€ã³ã¿: null ãã§ãã¯ã远å ããæ©æãªã¿ãŒã³ãã (
if source.is_null() { return; }) - å¯èªæ§: ãæåã® null ãã€ããèŠã€ãããåŠçãèªåã§å®è£ ããã®ã§ã¯ãªãã ååã«ãã¹ããããã©ã€ãã©ãªã䜿ã
ããã ããäžéšã®å®å šèŠä»¶ã¯é²åŸ¡çã«ãã§ãã¯ããããšãäžå¯èœã§ãã ããšãã°:ã
- ãã³ã°ãªã³ã°ãã€ã³ã¿
- ãã«çµç«¯ãã€ããååšããªãããš
ããã®é¢æ°ãã©ã®ããã«å¥å šã«ã§ããã§ããããïŒã
- 次ã®ãããã
sourceå ¥ååŒæ°ã®åããé·ããæ¢ç¥ã®ãã®ã«å€æŽãããã€ãŸããåã®äŸã®ããã« ã¹ã©ã€ã¹ã䜿ãã
- ãŸãã¯
- 颿°ã unsafe ãšããŠããŒã¯ãã
- å®å šæ§ã®äºåæ¡ä»¶ãææžåãã
ææžåãããå®å šæ§ã®åææ¡ä»¶
// Copyright 2026 Google LLC // SPDX-License-Identifier: Apache-2.0 #/// /// ... /// /// # å®å šæ§ /// /// ãã®é¢æ°ã¯ç°¡åã«æªå®çŸ©åäœãåŒãèµ·ããå¯èœæ§ããããŸãã以äžãæºããããšã確èªããŠãã ãã: /// /// - `source` ãã€ã³ã¿ã null ã§ã¯ãªãããã³ã°ãªã³ã°ããŠããªã /// - `source` ããŒã¿ã¯ããã®ã¡ã¢ãªå²ãåœãŠå ã§ãã«ãã€ãã§çµç«¯ããŠãã /// - `source` ããŒã¿ã¯è§£æŸãããªãïŒãã®ã©ã€ãã¿ã€ã äžå€æ¡ä»¶ãä¿ãããïŒ /// - `source` ããŒã¿ã¯ `isize::MAX` ãã€ãæªæºã§ãã pub unsafe fn copy(dest: &mut [u8], source: *const u8) { let source = { let mut len = 0; let mut end = source; // SAFETY: åŒã³åºãå ã null ã§ã¯ãªããã€ã³ã¿ãæäŸããŠãã while unsafe { *end != 0 } { len += 1; // SAFETY: åŒã³åºãå ãé·ã < isize:MAX ã®ããŒã¿ãæäŸããŠãã end = unsafe { end.add(1) }; } // SAFETY: åŒã³åºãå ãã©ã€ãã¿ã€ã ãšãšã€ãªã¢ã·ã³ã°ã®èŠä»¶ãç¶æããŠãã unsafe { std::slice::from_raw_parts(source, len + 1) } }; for (dest, src) in dest.iter_mut().zip(source) { *dest = *src; } } fn main() { let a = [114, 117, 115, 116].as_ptr(); let b = &mut [82, 85, 83, 84, 0]; println!("{}", String::from_utf8_lossy(b)); unsafe { copy(b, a); } println!("{}", String::from_utf8_lossy(b)); }
以åã®å埩ããã®å€æŽç¹:
copyã unsafe ãšããŠããŒã¯- å®å šæ§ã®åææ¡ä»¶ãææžå
- ã€ã³ã©ã€ã³ã®å®å šæ§ã³ã¡ã³ã
unsafe 颿°ã¯ããã®å®å šæ§ã®åææ¡ä»¶ãšå éšã® unsafe ãããã¯ã®äž¡æ¹ãææžåãããŠãããšãã«å¥å šã§ãã
main ã«ä¿®æ£ãå¿
èŠã§ãã
aã¯copyã®åææ¡ä»¶ã® 1 ã€ãæºãããŠããŸããïŒsource` ããŒã¿ã¯ã ãã®ã¡ã¢ãªå²ãåœãŠå ã§ãã«ãã€ãã§çµç«¯ããŠããïŒ- SAFETY ã³ã¡ã³ããå¿ èŠ
ãªãªã«ãå°å¹Ž
// Copyright 2026 Google LLC // SPDX-License-Identifier: Apache-2.0 pub unsafe fn copy(dest: &mut [u8], source: &[u8]) { for (dest, src) in dest.iter_mut().zip(source) { *dest = *src; } } fn main() { let a = &[114, 117, 115, 116]; let b = &mut [82, 85, 83, 84]; println!("{}", String::from_utf8_lossy(b)); unsafe { copy(b, a) }; println!("{}", String::from_utf8_lossy(b)); }
ããããããªãªã«ãå°å¹Žé¢æ°ãäœãããšãã§ããŸãã
ããã㯠unsafe ãšããŠããŒã¯ãããŠãããã®ã®ãããã°ã©ããŒã確èªããå¿ èŠã®ããå®å šæ§ã®äºåæ¡ä»¶ãæããªã颿°ã§ãã
å¥å šãª Rust ã® 3 ã€ã®åœ¢
- Safe Rust ã®ã¿ã§æžããã颿°
- 誀çšãäžå¯èœãª
unsafeãããã¯ãå«ã颿° - å®å šæ§ã®äºåæ¡ä»¶ãææžåããã unsafe 颿°
- ç§ãã¡ã¯å¥å šãªã³ãŒããæžããããšèããŠããŸãã
- å¥å
šãªã³ãŒããåããã圢ã¯ã次ã®ãã®ã ãã§ãã
unsafeãããã¯ãå«ãŸãªãå®å šãªé¢æ°unsafeãããã¯ãå®å šã«ã«ãã»ã«åããå®å šãªé¢æ°ãã€ãŸããåŒã³åºãå ããããã«ã€ããŠç¥ã£ãŠããå¿ èŠããªããã®unsafeãããã¯ãå«ããã®ã®ãããããã«ãã»ã«åããã蚌æã®è²¬ä»»ãåŒã³åºãå ã«æž¡ã unsafe 颿°
- 蚌æè²¬ä»»
- Safe Rust ã®ã¿ãããªãå®å šãªé¢æ° -> ã³ã³ãã€ã©
unsafeãããã¯ãå«ãå®å šãªé¢æ° -> 颿°ã®äœè- unsafe 颿° -> 颿°ã®åŒã³åºãå
å¥å šæ§ã®èšŒæ
å¥å šæ§
å¥å šãªé¢æ°ãšã¯ããã®å®å šæ§ã®äºåæ¡ä»¶ãæºããããŠããå Žåã« UB ãåŒãèµ·ãããªã颿°ã§ãã
-
å¥å šãªé¢æ°ã®å®çŸ©ãèªãã
-
åŒã³åºãåŽãå®è£ ããããã°ã©ããå®å šæ§ã®äºåæ¡ä»¶ãæºãã責任ãè² ã£ãŠãããã³ã³ãã€ã©ã¯å©ããŠãããªãããšãåŠçã«æãåºãããŠãã ããã
-
ç ããèšèã§èª¬æãããå¥å šæ§ãšã¯ããã®é¢æ°ãè¡åãããã«ãŒã«ã«åŸã£ãŠããããšãæå³ããŸããå®å šæ§ã®äºåæ¡ä»¶ãææžåãããŠãããåŒã³åºãåŽãããããæºãããŠããã°ããã®é¢æ°ã¯é©åã«æ¯ãèããŸãïŒUB ã¯çºçããŸããïŒã
å¥å šæ§ã®èšŒæïŒããŒã 2ïŒ
å¥å šãªé¢æ°ãšã¯ããã®å®å šæ§ã®åææ¡ä»¶ãæºããããŠãããªã UB ãåŒãèµ·ãããªã颿°ã®ããšã§ãã
ç³»: çŽç²ãª safe Rust ã§å®è£ ããããã¹ãŠã®é¢æ°ã¯å¥å šã§ããã
蚌æ:
-
safe Rust ã³ãŒãã«ã¯å®å šæ§ã®åææ¡ä»¶ããªãã
-
ãããã£ãŠãçŽç²ãª safe Rust ã§å®è£ ããã颿°ã®åŒã³åºãåŽã¯ãåææ¡ä»¶ã®ç©ºéåãåžžã«èªæã«æºããã
-
safe Rust ã³ãŒã㯠UB ãåŒãèµ·ãããªãã
QED.
-
ãã®ç³»ãèªãã
-
蚌æã説æããã
-
ãã ããèšãæ¹ã«ãããšããã¹ãŠã® safe Rust ã³ãŒãã¯ã¡ãããšããŠãããããã°ã©ããŒãèããªããã°ãªããªãå®å šæ§ã®åææ¡ä»¶ã¯ãªããåžžã«ã«ãŒã«ã«åŸããUB ãæ±ºããŠåŒãèµ·ãããªãã
éå¥å šæ§
å¥å šãªé¢æ°ãšã¯ãå®å šæ§ã®äºåæ¡ä»¶ãæºããããŠããéããUB ãåŒãèµ·ãããªã颿°ã®ããšã§ãã
éå¥å šãªé¢æ°ã¯ãææžåãããå®å šæ§ã®äºåæ¡ä»¶ãæºãããŠããŠããUB ãåŒãèµ·ããåŸãŸãã
éå¥å šãªã³ãŒã㯠æªã ãã®ã§ãã
-
éå¥å šãªé¢æ°ã®å®çŸ©ãèªãã§ãã ããã
-
ç ããèšãæ¹ã«ãããšãéå¥å šãªã³ãŒãã¯ãããããŸããããããããã§ã¯æ§ãããããŸããéå¥å šãªã³ãŒãã¯æªãã®ã§ããææžåãããã«ãŒã«ã©ããã«æ¯ãèã£ãŠããŠããéå¥å šãªã³ãŒãã¯ããã§ã UB ãåŒãèµ·ããåŸãŸãïŒ
-
ç§ãã¡ã¯ããªããžããªã«éå¥å šãªã³ãŒããäžåå«ãŸããŠããŠã»ãããããŸããã
-
éå¥å šãªã³ãŒããèŠã€ããããšããã³ãŒãã¬ãã¥ãŒã®ç¬¬äžã®ç®æšã§ãã
ã¡ã¢ãªã®ã©ã€ããµã€ã¯ã«
ãªããžã§ã¯ãïŒå€ïŒãçæã»ç Žæ£ãããã«ã€ããŠãã¡ã¢ãªã¯ããŸããŸãªæ®µéãçµãŸãã
| ã¡ã¢ãªã®ç¶æ | Safe Rust ããèªã¿åãå¯èœã? |
|---|---|
| å©çšå¯èœ | ããã |
| å²ãåœãŠæžã¿ | ããã |
| åæåæžã¿ | ã¯ã |
ãã®ã»ã¯ã·ã§ã³ã§ã¯ããªãã¬ãŒãã£ã³ã°ã·ã¹ãã ããæž¡ãããã¡ã¢ãªããããã°ã©ã å ã®æå¹ãªå€æ°ã«ãªããŸã§ã«äœãèµ·ãããã説æããŸãã
ã¡ã¢ãªãå©çšå¯èœãªç¶æ ã§ã¯ããªãã¬ãŒãã£ã³ã°ã·ã¹ãã ããã®ã¡ã¢ãªãç§ãã¡ã®ããã°ã©ã ã«æäŸããŠããŸãã
ã¡ã¢ãªãå²ãåœãŠæžã¿ã®ç¶æ ã§ã¯ãããã«å€ãæžã蟌ããããã«äºçŽãããŠããŸãããããæªåæåã¡ã¢ãªãšåŒã³ãŸãã
ã¡ã¢ãªãåæåæžã¿ã®ç¶æ ã§ã¯ãããããå®å šã«èªã¿åãããšãã§ããŸãã
åæå
MaybeUninit
MaybeUninit<T> ã䜿ããšãRust ã§æªåæåã¡ã¢ãªãæ±ããŸãã
// èäœæš© 2026 Google LLC // SPDX-License-Identifier: Apache-2.0 use std::mem::MaybeUninit; fn main() { let uninit = MaybeUninit::<&i32>::uninit(); println!("{uninit:?}"); }
ãå®å šãª Rust ã§ã¯ãæªåæåã®å¯èœæ§ãããããŒã¿ãåç §ããããšã¯ã§ããŸããã
ããããããã¹ãŠã®ããŒã¿ã¯æªåæåã®ç¶æ ã§ããã°ã©ã ã«å ¥ã£ãŠããŸããã
ããããã£ãŠãã¡ã¢ãªããã®ç¶æ
ãé·ç§»ã§ããããã«ããããã®æ©æž¡ããåã·ã¹ãã ã« å¿
èŠã§ããMaybeUninit<T> ããã®åã§ããã
ãMaybeUninit<T> 㯠Option<T> åãšéåžžã«ãã䌌ãŠããŸããããã® ã»ãã³ãã£ã¯ã¹ã¯å€§ããç°ãªããŸããMaybeUninit<T> ã«ããã Option::None ã«çžåœãããã®ã¯æªåæåã¡ã¢ãªã§ãããããã¯æžã蟌ã¿ã ããå®å
šã§ããã
ãæªåæåã§ããå¯èœæ§ã®ããã¡ã¢ãªããèªã¿åãã®ã¯ã極ããŠå±éºã§ããã
MaybeUninit ãšé å
// èäœæš© 2026 Google LLC // SPDX-License-Identifier: Apache-2.0 use std::mem::MaybeUninit; use std::ptr; fn main() { let input = b"RUST"; let mut buf = [const { MaybeUninit::<u8>::uninit() }; 2048]; // ã¡ã¢ãªã«å€ãæžã蟌ãã§èŠçŽ ãåæåãã for (i, input_byte) in input.iter().enumerate() { unsafe { let dst = buf.as_mut_ptr().add(i); ptr::write((*dst).as_mut_ptr(), *input_byte); } } // é åã®äžéšãåæåãããŠããå Žåã¯ã // unsafe ã䜿ã£ãŠãã®éšåãåãåºãã let ptr_to_init_subslice = buf.as_ptr() as *const u8; let init = unsafe { std::slice::from_raw_parts(ptr_to_init_subslice, input.len()) }; let text = std::str::from_utf8(init).unwrap(); println!("{text}"); // åæåæžã¿ã®èŠçŽ ã¯æåã§ããããããªããã°ãªããªã for element in &mut buf[0..input.len()] { unsafe { element.assume_init_drop(); } } }
æªåæåã¡ã¢ãªã®é
åãäœæããã«ã¯ã::uninit() ã³ã³ã¹ãã©ã¯ã¿ã const ã³ã³ããã¹ãå
ã§äœ¿çšã§ããŸãã
éåžžã©ãããptr::write ã䜿ã£ãŠå€ãåæåããŸãã
.assume_init() ã¯é
åã§ã¯ããã»ã©ç°¡åã«ã¯äœ¿ããŸãããããã«ã¯ãã¹ãŠã®å€ã åæåãããŠããå¿
èŠããããŸããããããã¡ãåå©çšããå Žåã¯ãããªããªãããšããããŸãããã®äŸã§ã¯ã åæåæžã¿ã®ãã€ãã ãããã€ã³ã¿ã§åãåºããŠæååã¹ã©ã€ã¹ãäœæããŠããŸãã
éšåçã«åæåãããé
åã®ãµãã¹ã©ã€ã¹ãäœæããéã¯ã æææš©ãš drop ã®æ£ããå®è£
ã«æ³šæããŠãã ãããæ³šæ: MaybeUninit<T> 㯠ãã® T ã«å¯Ÿã㊠drop ãåŒã³åºããŸããã
MaybeUninit<[u8;2048]> 㯠[MaybeUninit::<u8>; 2048] ãšã¯ç°ãªããŸããããã¯ã æªåæåã¡ã¢ãªã®é
åãšã æªåæåã®èŠçŽ ãå«ãé
åã®éãã§ãã
MaybeUninit<[u8;2048]>ã¯ããã¹ãŠãç¡ããã§ããé åå šäœãå®å šã«åæåããŠããassume_initãåŒã³åºãããMaybeUninit<[u8; 2048]>ã®ãŸãŸä¿æããŠ[u8; 2048]ãšããŠè§Šããªãããã«ããªããã°ãªããŸããã[MaybeUninit<u8>; 2048]ã§ã¯èŠçŽ ã 1 ã€ãã€åæåã§ãããã®åŸã åæåæžã¿ã®å é éšåã ãã®ãµãã¹ã©ã€ã¹ãåãåºããstd::slice::from_raw_partsãéããŠããã[u8]ãšããŠæ±ããŸããslice_assume_init_refãå®å šãªã®ã¯ãã¹ã©ã€ã¹å ã®ãã¹ãŠã®èŠçŽ ã åæåãããŠããå Žåã ãã§ãããã®äŸã§ã¯ãã¡ããã©ãããã®ãã€ããæžã蟌ãã åŸã«ã®ã¿&buf[..input.len()]ãæž¡ããŠããŸããTã« drop ãå¿ èŠãªå Žåã¯ãåæåæžã¿ã®èŠçŽ ã«å¯ŸããŠassume_init_drop()ã æåã§åŒã³åºããªããã°ãªããŸããããããçããšã¡ã¢ãªãªãŒã¯ã«ãªããŸãããã ãã æªåæåã®èŠçŽ ã«å¯ŸããŠåŒã³åºãã®ã¯æªå®çŸ©åäœã§ãã
MaybeUninit::zeroed()
// èäœæš© 2026 Google LLC // SPDX-License-Identifier: Apache-2.0 use std::mem::{MaybeUninit, transmute}; fn main() { let mut x = [const { MaybeUninit::<u32>::zeroed() }; 10]; x[6].write(7); // SAFETY: `x` ã®ãã¹ãŠã®å€ã¯æžãèŸŒã¿æžã¿ã§ãã let x: [u32; 10] = unsafe { transmute(x) }; println!("{x:?}") }
ãMaybeUninit<T>::zeroed() 㯠MaybeUninit<T>::uninit() ã®ä»£æ¿ ã³ã³ã¹ãã©ã¯ã¿ã§ããããã¯ãã³ã³ãã€ã©ã«å¯Ÿã㊠T ã®ãããã ãŒãã§åããããæç€ºããŸããã
Q: ãã¡ã¢ãªã«ã¯æžãèŸŒã¿æžã¿ã§ããã«ãããããããå㯠MaybeUninit<T> ã®ãŸãŸã§ãããªããåãã人ã¯ããŸããïŒã
A: äžéšã®åã§ã¯ããã®å€ãéãŒããŸãã¯éãã«ã§ããå¿
èŠããããŸããå
žåçãªäŸ ã¯åç
§ã§ãããããã¯ä»ã®å€ãã®åã«ãåœãŠã¯ãŸããŸããNonZeroUsize æŽæ°åãããã®ä»²éã®ä»ã®åãèããŠã¿ãŠãã ããã
MaybeUninit.write() ãšä»£å ¥
// Copyright 2026 Google LLC // SPDX-License-Identifier: Apache-2.0 use std::mem::MaybeUninit; fn main() { let mut buf = MaybeUninit::<String>::uninit(); // åæå buf.write(String::from("Hello, Rust!")); // äžæžã buf.write(String::from("Hi again")); // ä»£å ¥ã§ã¯ MaybeUninit ã®å€å šäœã眮ãæããããã buf = MaybeUninit::new(String::from("Goodbye")); // å åŽã®å€ããããããããããšãç¢ºèª let _ = unsafe { buf.assume_init() }; }
å
åŽã®å€ã眮ãæãããšãdrop ã®ã»ãã³ãã£ã¯ã¹ãã»ãšãã©ã®åãšç°ãªãããã ã¡ã¢ãªãªãŒã¯ãåŒãèµ·ããå¯èœæ§ããããŸããMaybeUninit<T> ã¯ãã® T ã®ãã¹ãã©ã¯ã¿ãåŒã³åºããŸããã
MaybeUninit::write() 㯠ptr::write ã䜿ããŸããããã¯å€ãå
容ãèªã¿åã£ãã ãããããããããã«ããã®å Žã§ã¡ã¢ãªãåæåããŸããã¡ã¢ãªãæªåæåã§ãã å¯èœæ§ããããšãã«ã¯ãããã¯ãŸãã«æãŸããåäœã§ãããããã«ãã§ã«æå¹ãªå€ã å
¥ã£ãŠããå Žåã¯ãªãŒã¯ããããšãæå³ããŸãã
代å
¥ãããšãã° buf = MaybeUninit::new(value) ã¯ãMaybeUninit å
šäœã 眮ãæããŸããå€ã MaybeUninit ã¯ã ãŒããããããšã«ãããããããŸããã MaybeUninit ã«ã¯ T çšã®ãã¹ãã©ã¯ã¿ããªããããå
åŽã®å€ã¯ãããããããŸããã å€ãã¹ãããã«åæåæžã¿ã®å€ãå
¥ã£ãŠããå Žåããã㯠write() ãšåæ§ã« ãªãŒã¯ããŸãã
éåžžã® drop åäœãå¿
èŠãªå Žåã¯ãassume_init ãŸãã¯é¢é£ããã¡ãœããã®ããããã䜿ã£ãŠã ãã®å€ãåæåæžã¿ã§ããããšã Rust ã«äŒããå¿
èŠããããŸãã
ã¡ã¢ãªãåæåããæ¹æ³
æé :
MaybeUninit<T>ãäœæãã- ããã«å€ãæžã蟌ã
- Rust ã«ããã®ã¡ã¢ãªãåæåæžã¿ã§ããããšãéç¥ãã
// Copyright 2026 Google LLC // SPDX-License-Identifier: Apache-2.0 use std::mem::MaybeUninit; fn main() { // ã¹ããã 1: MaybeUninit ãäœæãã let mut uninit = MaybeUninit::uninit(); // ã¹ããã 2: æå¹ãªå€ãã¡ã¢ãªã«æžã蟌ã uninit.write(1); // ã¹ããã 3: ã¡ã¢ãªäœçœ®ãæå¹ã§ããããšãåã·ã¹ãã ã«äŒãã let init = unsafe { uninit.assume_init() }; println!("{init}"); }
æªåæåã¡ã¢ãªãæ±ãã«ã¯ãäžè¬çã«æ¬¡ã®ã¯ãŒã¯ãããŒã«åŸããŸã: äœæãæžã蟌ã¿ã 確èªã
-
MaybeUninit<T>ãäœæããŸãã::uninit()ã³ã³ã¹ãã©ã¯ã¿ã¯æã æ±çšçãªãã®ã§ãããæžã蟌ã¿ãåæã«è¡ãå¥ã®ãã®ããããŸãã -
T åã®å€ãæžã蟌ã¿ãŸãããã㯠safe Rust ããå©çšã§ããããšã«æ³šæããŠãã ãããsafe Rust ã« ãšã©ãŸãããšã¯æçšã§ãããªããªããæžã蟌ãå€ã æå¹ã§ããããšãä¿èšŒããªããã°ãªããªãããã§ãã
-
.assume_init()ã¡ãœããã䜿ã£ãŠããã®ã¡ã¢ãªãåæåæžã¿ã§ããããšã åã·ã¹ãã ã«ç¢ºèªãããŸãã
éšåçãªåæå
// Copyright 2026 Google LLC // SPDX-License-Identifier: Apache-2.0 use std::mem::MaybeUninit; fn main() { // let mut buf = [0u8; 2048]; let mut buf = [const { MaybeUninit::<u8>::uninit() }; 2048]; let external_data = b"Hello, Rust!"; let len = external_data.len(); for (dest, src) in buf.iter_mut().zip(external_data) { dest.write(*src); } // SAFETY: `buf` ã®ãã¡ã¡ããã© `len` ãã€ãã UTF-8 ããã¹ãã§åæåãã let text: &str = unsafe { let ptr: *const u8 = buf.as_ptr().cast::<u8>(); let init: &[u8] = std::slice::from_raw_parts(ptr, len); std::str::from_utf8_unchecked(init) }; println!("{text}"); }
ãã®ã³ãŒãã¯ãäœããã®å€éšãœãŒã¹ããããŒã¿ãåä¿¡ããç¶æ³ãã·ãã¥ã¬ãŒãããŠããŸãã
å€éšãœãŒã¹ãããããã¡ãžãã€ãåãèªã¿èŸŒããšããéåžžã¯åä¿¡ãããã€ãæ°ãããããŸãããMaybeUninit<T> ã䜿ããšãåé·ãªåæåãã¹ã®ã³ã¹ããæãããšãªãããããã¡ãäžåºŠã ã確ä¿ã§ããŸãã
æšæºçãªæ§æïŒbuf = [0u8; 2048]ïŒã§é
åãäœæãããšããããã¡å
šäœããŒãã§åããããŸããMaybeUninit<T> ã¯ãé åã¯ç¢ºä¿ãããã®ã®ããŸã ãã®ã¡ã¢ãªã«ã¯è§Šããªãããã³ã³ãã€ã©ã«äŒããŸãã
Q: ãã®ã³ãŒãã¹ããããã®ã©ã®éšåã .assume_init() ãšåæ§ã®åœ¹å²ãæãããŠããŸããïŒ A: ãã€ã³ã¿ã®ãã£ã¹ããšæé»ã®èªã¿åºãã§ãã
é
åå
šäœã«å¯Ÿã㊠assume_init() ãåŒã³åºãããšã¯ã§ããŸãããã»ãšãã©ã®èŠçŽ ãæªåæåã®ãŸãŸãªã®ã§ãããã¯äžå¥å
šã§ãã代ããã«ããã€ã³ã¿ã *const MaybeUninit<u8> ãã *const u8 ã«ãã£ã¹ãããåæåæžã¿ã®éšåã ãã察象ãšããã¹ã©ã€ã¹ãæ§ç¯ããŸãã
ãã³çã
ãã®ã³ãŒã¹ã®ãã®ã»ã°ã¡ã³ãã§ã¯ã次ã®å å®¹ãæ±ããŸãã
- ããã³çãããšã¯äœã
- ãªããããå¿ èŠãªã®ã
- Rust ããããã©ã®ããã«å®è£ ããŠããã
- ããã unsafe ããã³ FFI ãšã©ã®ããã«çžäºäœçšããã
æŠèŠ
segment outline
âãã³çããã€ãŸãå€ã®ã¡ã¢ãªã¢ãã¬ã¹ãåºå®ãããå Žæã«ä¿æããããšã¯ãRust ã«ãããããé£è§£ãªæŠå¿µã® 1 ã€ã§ããâ
âé垞㯠async ã³ãŒããããªãã¡ poll(self: Pin<&mut Self>) ã®äžã§ããèŠãããŸãããããã³çãã«ã¯ããåºãé©çšç¯å²ããããŸããâ
èªå·±åç §æ§é äœã intrusive ããŒã¿æ§é ãªã©ãunsafe ããŒã¯ãŒããªãã§ã¯ èšè¿°ãé£ããããããã¯äžå¯èœãªããŒã¿æ§é ããããŸãã
C++ ãšã® FFI ã¯ãããã«é¢é£ãã代衚çãªãŠãŒã¹ã±ãŒã¹ã§ããRust ã¯ã åç §ãæã€ãããã C++ ãªããžã§ã¯ããèªå·±åç §ããŒã¿æ§é ã§ããå¯èœæ§ã æ³å®ããªããã°ãªããŸããã
âãã®è¡çªããã詳ããçè§£ããã«ã¯ããŸã Rust ã®ã ãŒãã»ãã³ãã£ã¯ã¹ã ãã£ããçè§£ããŠããããšã確èªããå¿ èŠããããŸããâ
ãã³çããšã¯äœã
- ãã³çããããåã¯ããã®ã¡ã¢ãªã¢ãã¬ã¹ã倿Žã§ããªãïŒã ãŒãã§ããªãïŒ
- æãããŠããå€ã¯å®å šãªã³ãŒãã§ã¯ã ãŒãã§ããªã
Pin<Ptr> ã¯ããã³çããããå€ãžã®ã¢ã¯ã»ã¹æ¹æ³ãå¶åŸ¡ããããã«ãæææš©ã·ã¹ãã ãå©çšããŸããèšèªèªäœã倿Žããã®ã§ã¯ãªããRust ã®æææš©ã·ã¹ãã ã䜿ã£ãŠãã³çãã匷å¶ããŸããPin ã¯ãã®å
å®¹ãææãããã®å®å
šãª API ã®ã©ãã«ãã ãŒããåŒãèµ·ãããã®ã¯ãããŸããã
ããã¯æ¬¡ã§èª¬æãããŠããŸã
æŠå¿µçã«ã¯ããã³çãã¯ããã©ã«ãã®ã ãŒãã®æåãé²ããŸãã
ããã¯èšèªèªäœã®å€æŽã®ããã«èŠããŸãã
ããããPin ã©ãããŒã¯å®éã«ã¯èšèªã®åºæ¬çãªéšåãäœãå€ããŠããŸããã
Pin ã¯ã ãŒããèš±ãå®å
šãª API ãå
¬éããŠããŸããããããã£ãŠããããåäœã®ã³ããŒãé²ãããšãã§ããŸãã
Unsafe API ã§ã¯ãã©ã€ãã©ãªäœè
㯠Unpin ãå®è£
ããŠããªãåãã©ããã§ããŸãããåãä¿èšŒãç¶æããªããã°ãªããŸããã
Pin ã®ããã¥ã¡ã³ãã§ã¯ããpointer typesããšããçšèªã䜿ã£ãŠããŸãã
ãpointer typeããšããçšèªã¯ãèšèªã«ããããã€ã³ã¿ã®ããªããã£ãåãããã¯ããã«åºãæå³ãæã¡ãŸãã
ãpointer typeãã¯ãã¿ãŒã²ããã Unpin ãå®è£
ããŠãã Deref å®è£
åããã¹ãŠã©ããããŸãã
Rust ã®ã¹ã¿ã€ã«ã«é¢ããæ³šèš: ãã®ãã¬ã€ãå¢çã¯ãåèªäœã§ã¯ãªã ::new() ã³ã³ã¹ãã©ã¯ã¿ãŒã®ãã¬ã€ãå¢çã«ãã£ãŠåŒ·å¶ãããŸãã
Rust ã«ãããã ãŒããšã¯äœã
åžžã«ãããåäœã®ã³ããŒã§ãããCopy ãå®è£
ããŠããªãåã§ãã£ãŠãåæ§ã§ãã
// Copyright 2026 Google LLC // SPDX-License-Identifier: Apache-2.0 #[derive(Debug, Default)] pub struct DynamicBuffer { data: Vec<u8>, position: usize, }; pub fn move_and_inspect(x: DynamicBuffer) { println!("{x:?}"); } pub fn main() { let a = DynamicBuffer::default(); let mut b = a; b.data.push(b'R'); b.data.push(b'U'); b.data.push(b'S'); b.data.push(b'T'); move_and_inspect(b); }
move_and_expect() ã®åŒã³åºãã«å¯ŸããŠçæããã LLVM IR:
call void @llvm.memcpy.p0.p0.i64(ptr align 8 %_12, ptr align 8 %b, i64 32, i1 false)
invoke void @move_and_inspect(ptr align 8 %_12)
- 倿°
%bãã%_12ãžã®memcpy %_12ïŒã³ããŒïŒã䜿ã£ãŠmove_and_inspectãåŒã³åºã
DynamicBuffer 㯠Copy ãå®è£
ããŠããªãããšã«æ³šæããŠãã ããã
瀺åãããããš: å€ã®ã¡ã¢ãªã¢ãã¬ã¹ã¯å®å®ããŠããŸããã
ç§»åããããåäœã®ã³ããŒã§ããããšã瀺ãã«ã¯ãplayground ã§ã³ãŒããéãããŸã㯠the Compiler Explorer ãåç §ããŠãã ããã
ã¢ã»ã³ããªåºåã®ã»ãããã人åã:
The Compiler Explorer ã¯ãçæãããã¢ã»ã³ããªãè°è«ããã®ã«äŸ¿å©ã§ããmain 颿°å
ã®ã¢ã»ã³ããªåºåã® 128-136 è¡ç®ã«ã«ãŒãœã«ãåãããŠãã ããïŒãã³ã¯ã§ãã€ã©ã€ããããã¯ãã§ãïŒã
move_and_inspect ã«å¯ŸããŠçæãããé¢é£ã³ãŒãåºå:
mov rax, qword ptr [rsp + 16]
mov qword ptr [rsp + 48], rax
mov rax, qword ptr [rsp + 24]
mov qword ptr [rsp + 56], rax
movups xmm0, xmmword ptr [rsp]
movaps xmmword ptr [rsp + 32], xmm0
lea rdi, [rsp + 32]
call qword ptr [rip + move_and_inspect@GOTPCREL]
Pin ã®å®çŸ©
// Copyright 2026 Google LLC
// SPDX-License-Identifier: Apache-2.0
#[repr(transparent)]
pub struct Pin<Ptr> {
pointer: Ptr,
}
impl<Ptr: Deref<Target: Unpin>> Pin<Ptr> {
pub fn new(pointer: Ptr) -> Pin<Ptr> { ... }
}
impl<Ptr: Deref> Pin<Ptr> {
pub unsafe fn new_unchecked(pointer: Ptr) -> Pin<Ptr> { ... }
}
Pin 㯠ãã€ã³ã¿å ã«å¯Ÿããæå°éã®ã©ãããŒã§ããããã€ã³ã¿å ãšã¯ Deref ãå®è£
ããåãšããŠå®çŸ©ãããŸãã
ãã ããPin::new() ãåãä»ããã®ã¯ãUnpin ãå®è£
ããã¿ãŒã²ããã«ããªãã¡ã¬ã³ã¹ãããå (Deref<Target: Unpin>) ã®ã¿ã§ããããã«ãããPin ã¯åã·ã¹ãã ã«ãã®ä¿èšŒã®åŒ·å¶ãå§ããããšãã§ããŸãã
Unpin ãå®è£
ããªãåãããªãã¡ pinning ãå¿
èŠãšããåã¯ãunsafe 㪠Pin::new_unchecked() ãä»ã㊠Pin ãäœæããªããã°ãªããŸããã
è£è¶³: ä»ã® new()/new_unchecked() ã¡ãœããã®çµãšã¯ç°ãªããnew ã¯å®è¡æãã§ãã¯ãäžåè¡ããŸããããã®ãã§ãã¯ã¯ãŒãã³ã¹ãã®ã³ã³ãã€ã«æãã§ãã¯ã§ãã
ãªã Pin ã¯äœ¿ãã«ããã®ã
Pin<Ptr>ã¯ãåãªããæšæºã©ã€ãã©ãªã§å®çŸ©ãããåã§ã- ããã¯ãã³ã¢èšèªãæ¡åŒµããããšãªããå ã ã®å¯Ÿè±¡èªè ã§ãã£ã async ã©ã³ã¿ã€ã ã®äœæè ã®ããŒãºãæºãããŠããŸãã
- ãã®èªè
å±€ã¯ããã®äœ¿ãåæã®é¢ã§ã®æ¬ ç¹ãããçšåºŠåãå
¥ããããŸããã
asyncã®ãŠãŒã¶ãŒãPinãçŽæ¥æ±ãããšã¯ãã£ãã«ãªãã£ãããã§ã
âãªã Pin ã¯ããã»ã©æ±ãã¥ããã®ããšçåã«æããããããŸããããã®çãã¯äž»ã« æŽå²çãªçµç·¯ã«ãããã®ã§ããâ
âPin<Ptr> ã¯ãä»£æ¿æ¡ããã Rust ãããžã§ã¯ãã«ãšã£ãŠå®è£
ãç°¡åã§ãããâ
âPin ã¯ãäž»ã«äžçã§ async ã©ã³ã¿ã€ã ãæžãããã 100 人ã®ããã«èšèšãããŸããã Rust ããŒã ã¯ãããåçŽã§ã¯ãããã®ã®ïŒã³ã³ãã€ã©ã«ãšã£ãŠïŒã䜿ãåæã«å£ã èšèšãéžã³ãŸãããâ
âãã䜿ããããææ¡ãååšããŸããããäž»èŠãªå¯Ÿè±¡èªè ã«ãšã£ãŠã¯è€éããããšã㊠åŽäžãããŸããããããããã®èªè å±€ã¯ãã®è€éãã«å¯ŸåŠã§ããŸãããâ
Unpin ãã¬ã€ã
Unpinåã¯ãPinã§ã©ãããããŠããå Žåã§ããèªç±ã«ç§»åã§ããŸã- ã»ãšãã©ã®åã¯
Unpinãå®è£ ããŸãããã㯠âauto traitâ ã ããã§ã auto traitã®æåã¯å€æŽã§ããŸã:!Unpinåã¯æ±ºããŠç§»åããŠã¯ãªããŸããPhantomPinnedãã£ãŒã«ããå«ãåã¯ãããã©ã«ãã§ã¯Unpinãå®è£ ããŸãã
åã Unpin ãå®è£
ããŠããå ŽåãPin<Ptr> ã®ãã³çãã®æå㯠çºåããªãããšã説æããŠãã ãããå€ã¯èªç±ã«ç§»åã§ããŸãã
ã»ãšãã©ãã¹ãŠã®åã Unpin ãå®è£
ããŠããããšã説æããŠãã ããããã㯠ã³ã³ãã€ã©ã«ãã£ãŠèªåçã«å®è£
ãããŸãã
Unpin ãå®è£
ããåã¯ã次ã®ããã«èšã£ãŠããããšã«ãªããŸã: ãèªå·±åç
§ãæããªãããšãçŽæããã®ã§ã ç§ãç§»åããŠãåžžã«å®å
šã§ããã
åã: ã©ã®ãããªåã !Unpin ã«ãªãåŸãã§ãããã?
- ã³ã³ãã€ã©çæã® futures
PhantomPinnedãã£ãŒã«ããå«ãå- C++ ãªããžã§ã¯ããã©ããããäžéšã®å
!Unpin åã¯ããã£ãããã³çãããããšç§»åã§ããŸãã
PhantomPinned
å®çŸ©
// Copyright 2026 Google LLC
// SPDX-License-Identifier: Apache-2.0
pub struct PhantomPinned;
impl !Unpin for PhantomPinned {}
äœ¿çšæ³
// Copyright 2026 Google LLC // SPDX-License-Identifier: Apache-2.0 pub struct DynamicBuffer { data: Vec<u8>, cursor: std::ptr::NonNull<u8>, _pin: std::marker::PhantomPinned, }
PhantomPinned ã¯ããŒã«ãŒåã§ãã
åã PhantomPinned ãå«ãã§ããå Žåããã®åã¯ããã©ã«ãã§ã¯ Unpin ãå®è£
ããŸããã
ããã«ãããDynamicBuffer ã Pin ã§ã©ããããããšããã³çãã匷å¶ãããŸãã
èªå·±åç §ãããã¡ã®äŸ
ãèªå·±åç §ãããã¡ããšã¯ãèªèº«ã®ãã£ãŒã«ãã® 1 ã€ãžã®åç §ãæã€ åã§ã:
// èäœæš© 2026 Google LLC
// SPDX-License-Identifier: Apache-2.0
pub struct SelfReferentialBuffer {
data: [u8; 1024],
cursor: *mut u8,
}
ãã®çš®ã®æ§é 㯠Rust ã§ã¯äžè¬çã§ã¯ãããŸãããSelfReferentialBuffer ã® ã€ã³ã¹ã¿ã³ã¹ãç§»åãããšãã«ãcursor ã®ã¢ãã¬ã¹ãæŽæ°ããæ¹æ³ããªãããã§ãã
ãããããã®ãããªæ§æã¯ãã¬ããŒãžã³ã¬ã¯ã·ã§ã³ãæäŸããä»ã®èšèªãã ã ãŒããã³ããŒã®éã®ç¬èªã®æ¯ãèãããŠãŒã¶ãŒãå®çŸ©ã§ãã C++ ã§ã¯ã ããèªç¶ã§ãã
æŠèŠ
segment outline
C++ ã§ã®ã¢ãã«å
#include <cstddef>
#include <cstring>
class SelfReferentialBuffer {
std::byte data[1024];
std::byte* cursor = data;
public:
SelfReferentialBuffer(SelfReferentialBuffer&& other)
: cursor{data + (other.cursor - other.data)}
{
std::memcpy(data, other.data, 1024);
}
};
Compiler Explorer ã§ç¢ºèªãã
SelfReferentialBuffer ã«ã¯ 2 ã€ã®ã¡ã³ããŒããããdata 㯠1 ãããã€ãã®ã¡ã¢ãªã§ãcursor ã¯ãã®åè
ãæããã€ã³ã¿ã§ãã
ãã®ã ãŒãã³ã³ã¹ãã©ã¯ã¿ã¯ãcursor ãæ°ããã¡ã¢ãªã¢ãã¬ã¹ã«æŽæ°ãããããšãä¿èšŒããŸãã
ãã®åã Rust ã§ç°¡åã«è¡šçŸããããšã¯ã§ããŸããã
Rust ã§ã®ã¢ãã«å
// Copyright 2026 Google LLC
// SPDX-License-Identifier: Apache-2.0
/// çãã€ã³ã¿
pub struct SelfReferentialBuffer {
data: [u8; 1024],
cursor: *mut u8,
}
/// æŽæ°ãªãã»ãã
pub struct SelfReferentialBuffer {
data: [u8; 1024],
cursor: usize,
}
/// Pinning
pub struct SelfReferentialBuffer {
data: [u8; 1024],
cursor: *mut u8,
_pin: std::marker::PhantomPinned,
}
åè: å ã® C++ ã¯ã©ã¹å®çŸ©
class SelfReferentialBuffer {
char data[1024];
char* cursor;
};
æ¬¡ã®æ°æã®ã¹ã©ã€ãã§ã¯ãå ã® C++ ãšåãã»ãã³ãã£ã¯ã¹ãæã€ Rust ã®åãäœæããããã® 3 ã€ã®ã¢ãããŒãã瀺ããŸãã
- çãã€ã³ã¿ã䜿çšãã: C++ ã«éåžžã«è¿ãã§ãããåŸãããåã®äœ¿çšã¯æ¥µããŠå±éºã§ã
- æŽæ°ãªãã»ãããä¿åãã: Rust ã§ã¯ããèªç¶ã§ãããåç §ã¯æåã§äœæããå¿ èŠããããŸã
- Pinning: ããå°ãªã
unsafeãããã¯ã§çãã€ã³ã¿ãæ±ããŸã
çãã€ã³ã¿ã䜿ã
// Copyright 2026 Google LLC // SPDX-License-Identifier: Apache-2.0 #[derive(Debug)] pub struct SelfReferentialBuffer { data: [u8; 1024], cursor: *mut u8, } impl SelfReferentialBuffer { pub fn new() -> Self { let mut buffer = SelfReferentialBuffer { data: [0; 1024], cursor: std::ptr::null_mut() }; buffer.update_cursor(); buffer } // å±éº: ã ãŒãã®ãã³ã«åŒã³åºããªããã°ãªããªã pub fn update_cursor(&mut self) { self.cursor = self.data.as_mut_ptr(); } pub fn read(&self, n_bytes: usize) -> &[u8] { unsafe { let start = self.data.as_ptr(); let end = start.add(1024); let cursor = self.cursor as *const u8; assert!((start..=end).contains(&cursor), "cursor is out of bounds"); let available = end.offset_from(cursor) as usize; let len = n_bytes.min(available); std::slice::from_raw_parts(cursor, len) } } pub fn write(&mut self, bytes: &[u8]) { unsafe { let start = self.data.as_mut_ptr(); let end = start.add(1024); assert!((start..=end).contains(&self.cursor), "cursor is out of bounds"); let available = end.offset_from(self.cursor) as usize; let len = bytes.len().min(available); std::ptr::copy_nonoverlapping(bytes.as_ptr(), self.cursor, len); self.cursor = self.cursor.add(len); } } }
ããã§ã¯ããŸãæéããããããªãã§ãã ããã
èŠç¹:
unsafeãé »ç¹ã«çŸããããšã匷調ããŠãã ãããããã¯ãå¥ã®èšèšã®ã»ããããé©åãããããªãããšã瀺åããŠããŸããunsafeãããã¯ã«å®å šæ§ã³ã¡ã³ãããããŸããããã®ããããã®ã³ãŒãã¯äžå¥å šã§ããunsafeãããã¯ãåºãããŸããããå®è·µã§ã¯ãããå°ããªunsafeãããã¯ã䜿ããå ·äœçãªæ¯ãèããå ·äœçãªäºåæ¡ä»¶ãå ·äœçãªå®å šæ§ã³ã¡ã³ãã䌎ãããŸãã
質å:
Q: read() ã¡ãœãããš write() ã¡ãœãã㯠unsafe ãšããŠããŒã¯ãã¹ãã§ããïŒ
A: ã¯ããæžã蟌ã¿ãè¡ããããŸã§ã¯ self.cursor 㯠null ãã€ã³ã¿ã«ãªãããã§ãã
ãªãã»ããã䜿çšãã
// Copyright 2026 Google LLC // SPDX-License-Identifier: Apache-2.0 #[derive(Debug)] pub struct SelfReferentialBuffer { data: [u8; 1024], position: usize, } impl SelfReferentialBuffer { pub fn new() -> Self { SelfReferentialBuffer { data: [0; 1024], position: 0 } } pub fn read(&self, n_bytes: usize) -> &[u8] { let available = self.data.len().saturating_sub(self.position); let len = n_bytes.min(available); &self.data[self.position..self.position + len] } pub fn write(&mut self, bytes: &[u8]) { let available = self.data.len().saturating_sub(self.position); let len = bytes.len().min(available); self.data[self.position..self.position + len].copy_from_slice(&bytes[..len]); self.position += len; } }
Rust ã§ã¯ããªãã»ãã倿°ã䜿çšããå¿ èŠã«å¿ããŠåç §ãäœæããã»ãããããæ £çšçã§ãã
Pin<Ptr> ã䜿ã
Pinning ã䜿ããšãRust ããã°ã©ããŒã¯ C++ ã®ã¯ã©ã¹ã«ã¯ããã«è¿ãåãäœæã§ããŸãã
// Copyright 2026 Google LLC // SPDX-License-Identifier: Apache-2.0 use std::marker::PhantomPinned; use std::pin::Pin; /// ç§»åã§ããªãèªå·±åç §ãããã¡ã #[derive(Debug)] pub struct SelfReferentialBuffer { data: [u8; 1024], cursor: *mut u8, _pin: PhantomPinned, } impl SelfReferentialBuffer { pub fn new() -> Pin<Box<Self>> { let buffer = SelfReferentialBuffer { data: [0; 1024], cursor: std::ptr::null_mut(), _pin: PhantomPinned, }; let mut pinned = Box::pin(buffer); unsafe { let mut_ref = Pin::get_unchecked_mut(pinned.as_mut()); mut_ref.cursor = mut_ref.data.as_mut_ptr(); } pinned } pub fn read(&self, n_bytes: usize) -> &[u8] { unsafe { let start = self.data.as_ptr(); let end = start.add(self.data.len()); let cursor = self.cursor as *const u8; assert!((start..=end).contains(&cursor), "cursor is out of bounds"); let offset = cursor.offset_from(start) as usize; let available = self.data.len().saturating_sub(offset); let len = n_bytes.min(available); &self.data[offset..offset + len] } } pub fn write(mut self: Pin<&mut Self>, bytes: &[u8]) { let this = unsafe { self.as_mut().get_unchecked_mut() }; unsafe { let start = this.data.as_mut_ptr(); let end = start.add(1024); assert!((start..=end).contains(&this.cursor), "cursor is out of bounds"); let available = end.offset_from(this.cursor) as usize; let len = bytes.len().min(available); std::ptr::copy_nonoverlapping(bytes.as_ptr(), this.cursor, len); this.cursor = this.cursor.add(len); } } }
颿°ã·ã°ããã£ãå€ãã£ãŠããããšã«æ³šç®ããŠãã ãããããšãã°ã::new() 㯠Self ã§ã¯ãªã Pin<Box<Self>> ãè¿ããŸããããã¯ããŒãå²ãåœãŠã䌎ããŸãã Pin<Ptr> 㯠Box ã®ãããªãã€ã³ã¿åãšãšãã«åäœããå¿
èŠãããããã§ãã
::new() ã§ã¯ãPin::get_unchecked_mut() ã䜿ã£ãŠããã³çãããã åŸã® ãããã¡ãžã®å¯å€åç
§ãååŸããŠããŸããããã¯ãcursor ãåæåããããã«ã äžæçã« pinning ã®ä¿èšŒãç Žã£ãŠãããã unsafe ã§ãããã®æç¹ä»¥éã SelfReferentialBuffer ãç§»åããªãããã«ããªããã°ãªããŸãããPin ã®å®å
šæ§å¥çŽã§ã¯ã ãã£ããå€ããã³çãããããšãdrop ããããŸã§ãã®ã¡ã¢ãªäœçœ®ã¯åºå®ãããŸãã
Pin<Ptr> ãš Drop
ãã³çãããã !Unpin åã«ãããéèŠãªèª²é¡ã® 1 ã€ã¯ãDrop ãã¬ã€ããå®è£
ããããšã§ãã drop ã¡ãœãã㯠&mut self ãåãåããããå€ãã ãŒãã§ããŠããŸããŸãããããã ãã³çããããå€ã¯ã ãŒãããŠã¯ãªããŸããã
誀ã£ã Drop å®è£
drop ã®äžã§èª€ã£ãŠå€ãã ãŒãããŠããŸãã®ã¯ç°¡åã§ãã代å
¥ã ptr::readãmem::replace ã®ãããªæäœã¯ãæ°ä»ããªããã¡ã«ãã³çãã® ä¿èšŒãç Žãå¯èœæ§ããããŸãã
// èäœæš© 2026 Google LLC // SPDX-License-Identifier: Apache-2.0 struct SelfRef { data: String, ptr: *const String, } impl Drop for SelfRef { fn drop(&mut self) { // æªãäŸ: `ptr::read` 㯠`self.data` ã `self` ããã ãŒãããŠããŸããŸãã // 颿°ã®æ«å°Ÿã§ `_dupe` ãããããããããšãäºéè§£æŸã«ãªããŸãïŒ let _dupe = unsafe { std::ptr::read(&self.data) }; } }
ãã³çããããåã¯ãã¡ã¢ãªã®å®å®æ§ã«ã€ããŠä¿èšŒãæäŸããŸããptr::read ã mem::replace ã®ãããªæäœã¯ãããŒã¿ãã ãŒããŸãã¯è€è£œããããšã§ã åã·ã¹ãã ã«èªèãããªããŸãŸå
éšãã€ã³ã¿ãç¡å¹ã«ãããããã®ä¿èšŒã æ°ä»ããªããã¡ã«ç Žãå¯èœæ§ããããŸãã
ãã® drop() ã¡ãœããã§ã¯ã_dupe 㯠self.data ã®ãããåäœã®ã³ããŒã§ããã¡ãœããã®æåŸã§ã ãã㯠self ãšãšãã«ãããããããŸãããã®äºéããããã¯æªå®çŸ©åäœã§ãã
æ£ãã Drop å®è£
!Unpin åã«å¯Ÿã㊠Drop ãæ£ããå®è£
ããã«ã¯ãå€ãã ãŒããããªãããšã ä¿èšŒããªããã°ãªããŸãããäžè¬çãªãã¿ãŒã³ã¯ãPin<&mut T> ã«å¯Ÿã㊠æäœãããã«ããŒé¢æ°ãäœãããšã§ãã
// èäœæš© 2026 Google LLC // SPDX-License-Identifier: Apache-2.0 use std::marker::PhantomPinned; use std::pin::Pin; struct SelfRef { data: String, ptr: *const String, _pin: PhantomPinned, } impl SelfRef { fn new(data: impl Into<String>) -> Pin<Box<SelfRef>> { let mut this = Box::pin(SelfRef { data: data.into(), ptr: std::ptr::null(), _pin: PhantomPinned, }); let ptr: *const String = &this.data; // SAFETY: èªå·±åç §ãäœãåã« `this` ã¯ãã§ã«ãã³çããããŠããŸãã unsafe { Pin::as_mut(&mut this).get_unchecked_mut().ptr = ptr; } this } // ãã®é¢æ°ã¯ããã³çãããã `SelfRef` ã«å¯ŸããŠã®ã¿åŒã³åºããŸãã unsafe fn drop_pinned(self: Pin<&mut SelfRef>) { // `self` ã¯ãã³çããããŠããã®ã§ãããããå€ãã ãŒãããŠã¯ãªããŸããã println!("dropping {}", self.data); } } impl Drop for SelfRef { fn drop(&mut self) { // `drop` ã¯ãã®å€ã䜿ãããæåŸã®æ©äŒãªã®ã§ã`drop_pinned` ã // å®å šã«åŒã³åºããŸãã`self` ããã®åŸã ãŒããããªãããšãåãã£ãŠ // ããããã`new_unchecked` ã䜿ããŸãã unsafe { SelfRef::drop_pinned(Pin::new_unchecked(self)); } } } fn main() { let _pinned = SelfRef::new("Hello, "); } // ãã³çããããå€ãã ãŒãããã« `Drop` ãå®è¡ãããŸã
å®äŸ: !Unpin åã« Drop ãå®è£
ãã
// èäœæš© 2026 Google LLC
// SPDX-License-Identifier: Apache-2.0
use std::cell::RefCell;
use std::marker::PhantomPinned;
use std::mem;
use std::pin::Pin;
thread_local! {
static BATCH_FOR_PROCESSING: RefCell<Vec<String>> = RefCell::new(Vec::new());
}
#[derive(Debug)]
struct CustomString(String);
#[derive(Debug)]
struct SelfRef {
data: CustomString,
ptr: *const CustomString,
_pin: PhantomPinned,
}
impl SelfRef {
fn new(data: &str) -> Pin<Box<SelfRef>> {
let mut boxed = Box::pin(SelfRef {
data: CustomString(data.to_owned()),
ptr: std::ptr::null(),
_pin: PhantomPinned,
});
let ptr: *const CustomString = &boxed.data;
unsafe {
Pin::get_unchecked_mut(Pin::as_mut(&mut boxed)).ptr = ptr;
}
boxed
}
}
impl Drop for SelfRef {
fn drop(&mut self) {
// SAFETY: String ãããã€ããèªã¿åã£ãŠããããå®å
š
let payload = unsafe { std::ptr::read(&self.data) };
BATCH_FOR_PROCESSING.with(|log| log.borrow_mut().push(payload.0));
}
}
fn main() {
let pinned = SelfRef::new("Rust ðŠ");
drop(pinned);
BATCH_FOR_PROCESSING.with(|batch| {
println!("Batch: {:?}", batch.borrow());
});
}
ãã®äŸã§ã¯ããã¬ã¡ããªããã®ã³ã°ãªã©ã®åŸåŠçã®ããã®ããŒã¿ã远å ããããã« Drop ãã¬ã€ãã䜿çšããŠããŸãã
ãã® Safety ã³ã¡ã³ãã¯èª€ã£ãŠããŸãã ptr::read ã¯ãããåäœã®ã³ããŒãäœæãããããself.data ã¯ç¡å¹ãªç¶æ
ã®ãŸãŸã«ãªããŸããself.data ã¯ã¡ãœããã®æ«å°Ÿã§ããäžåºŠããããããããããäºéè§£æŸã«ãªããŸãã
ã¯ã©ã¹ã«ã³ãŒããä¿®æ£ããŠããã£ãŠãã ããã
ææ¡ 0: åèšèš
åŸåŠçã·ã¹ãã ã Drop ã䜿ããã«åäœããããã«åèšèšããŠãã ããã
ææ¡ 1: Clone
.clone() ã䜿ãã®ã¯æåã®æçœãªéžæè¢ã§ãããã¡ã¢ãªã確ä¿ããŸãã
// èäœæš© 2026 Google LLC
// SPDX-License-Identifier: Apache-2.0
impl Drop for SelfRef {
fn drop(&mut self) {
let payload = self.data.0.clone();
BATCH_FOR_PROCESSING.with(|log| log.borrow_mut().push(payload));
}
}
ææ¡ 2: ManuallyDrop
CustomString ã ManuallyDrop ã§ã©ãããããšãDrop å®è£
ã®æ«å°Ÿã§ã®ïŒ2 åç®ã®ïŒèªåãããããé²ããŸãã
// èäœæš© 2026 Google LLC
// SPDX-License-Identifier: Apache-2.0
struct SelfRef {
data: ManuallyDrop<CustomString>,
ptr: *const CustomString,
_pin: PhantomPinned,
}
// ...
impl Drop for SelfRef {
fn drop(&mut self) {
// SAFETY: self.data
let payload = unsafe { ManuallyDrop::take(&mut self.data) };
BATCH_FOR_PROCESSING.with(|log| log.borrow_mut().push(payload.0));
}
}
FFI
èšèªéçžäºéçš
çæ³çãªã·ããªãª:
ãã®ã³ãŒã¹ã®ãã®ã»ã¯ã·ã§ã³ã§ã¯ãå€éšé¢æ°ã€ã³ã¿ãŒãã§ãŒã¹ (FFI) ãä»ãã Rust ãšå€éšèšèªãšã®çžäºäœçšã«ã€ããŠæ±ããç¹ã« C++ ãšã®çžäºéçšæ§ã«éç¹ã眮ããŸãã
çæ³çã«ã¯ãRust ãšå€éšèšèªïŒãã®å Žå㯠C++ïŒã®å©çšè 㯠äºãã®ã¡ãœãããçŽæ¥åŒã³åºããã¯ãã§ãã
ãã®çæ³çãªã·ããªãªãå®çŸããã®ã¯éåžžã«å°é£ã§ã:
èšèªããšã«ã»ãã³ãã£ã¯ã¹ãç°ãªãããããããã察å¿ä»ããã«ã¯ ãã¬ãŒããªãã䌎ããŸããRust ã C++ ã ABI ã®å®å®æ§1ãæäŸããŠããªãããã å®å®ããåºç€ã®äžã«æ§ç¯ããããšãå°é£ã§ã
-
äžéšã® C++ ã³ã³ãã€ã©ãã³ããŒã¯ãèªç€Ÿã® ããŒã«ãã§ãŒã³å ã§ ABI ã®å®å®æ§ããµããŒãããŠããŸãã â©
çžäºéçšã®æŠç¥
ããŒã¿æ§é ãã·ã³ãã«ãçŽæ¥å ±æããããšã¯éåžžã«å°é£ã§ã:
C ABI ãä»ãã FFI ã®ã»ãããã¯ããã«å®çŸããããã§ã:
ãã®ä»ã®æŠç¥:
- 忣ã·ã¹ãã (RPC)
- ã«ã¹ã¿ã ABIïŒã€ãŸã WebAssembly Interface TypesïŒ
é«å¿ å®åºŠã®çžäºéçš
çæ³çãªã·ããªãªã¯ãçŸåšã®ãšããå®é𿮵éã§ãã
ãããæ¢ç©¶ããŠãããããžã§ã¯ããšããŠãcrubit ãš Zngur ããããŸããåè ã¯ãäºææ§ã®ããåã ãã¡ã€ã³ããŸããã§ã·ãŒã ã¬ã¹ã«åäœã§ããããã«ãååŽã§ã°ã«ãŒã³ãŒããæäŸããŸããåŸè 㯠åçãã£ã¹ãããã«äŸåããC++ ãªããžã§ã¯ãã Rust ã« trait object ãšããŠåã蟌ã¿ãŸãã
C API ãä»ããäœå¿ å®åºŠã®çžäºéçš
çžäºéçšã®å žåçãªæŠç¥ã¯ãã€ã³ã¿ãŒãã§ãŒã¹ãšã㊠C èšèªã䜿ãããšã§ããC 㯠æå€±ã®ããã³ãŒããã¯ã§ãããã®æŠç¥ã§ã¯ãéåžžãäž¡åŽã§è€éãªã³ãŒããå¿ èŠã«ãªããŸãã
ãã®ä»ã®æŠç¥ ã¯ããŒãã³ã¹ãç°å¢ã§ã¯çŸå®æ§ãäœããªããŸãã
忣ã·ã¹ãã ã¯ã©ã³ã¿ã€ã ã³ã¹ãã䌎ããŸãã
å€éšã©ã€ãã©ãªã®ã¡ãœããåŒã³åºãã§ã¯ãã·ãªã¢ã©ã€ãºïŒè»¢éïŒãã·ãªã¢ã©ã€ãºã® åŸåŸ©ãçºçããããã倧ããªãªãŒããŒããããæããŸããäžè¬è«ãšããŠã ééç㪠RPC ã¯è¯ãèãã§ã¯ãããŸãããéã«ãããã¯ãŒã¯ãå ¥ãããã§ãã
wasm ãªã©ã® ã«ã¹ã¿ã ABI ã¯ãã©ã³ã¿ã€ã ãŸãã¯å€§ããªå®è£ ã³ã¹ããå¿ èŠãšããŸãã
èå¯: åå®å šæ§
èšèªã®éã
C ãæå°å ¬åæ¯ãšããŠäœ¿ããšããããšã¯ãRust ã C++ ã§å©çšã§ããè±ããªè¡šçŸåã®å€ãã倱ãããããšãæå³ããŸãã
å倿ã«ã¯ãæå³ã®åªå€±ãã©ã³ã¿ã€ã ãªãŒããŒãããããããŠæ°ä»ãã«ãããã°ãçããå¯èœæ§ããããŸãã
ç°ãªã衚çŸ
// Copyright 2026 Google LLC // SPDX-License-Identifier: Apache-2.0 fn main() { let c_repr = b"Hello, C\0"; let cc_repr = (b"Hello, C++\0", 10u32); let rust_repr = (b"Hello, Rust", 11); }
åèšèªã«ã¯ç©äºã®å®è£ æ¹æ³ã«ã€ããŠç¬èªã®èãæ¹ãããããããæ··ä¹±ããã°ã«ã€ãªããããšããããŸããããã¹ãã衚çŸãã 3 ã€ã®æ¹æ³ãèããŠã¿ãŸãããã
çã®è¡šçŸã Rust ã®æååã¹ã©ã€ã¹ã«å€æããæ¹æ³ã瀺ããŠãã ãã:
// Copyright 2026 Google LLC
// SPDX-License-Identifier: Apache-2.0
// C 衚çŸãã Rust ãž
unsafe {
let ptr = c_repr.as_ptr() as *const i8;
let c: &str = std::ffi::CStr::from_ptr(ptr).to_str().unwrap();
println!("{c}");
};
// C++ 衚çŸãã Rust ãž
unsafe {
let ptr = cc_repr.0.as_ptr();
let bytes = std::slice::from_raw_parts(ptr, cc_repr.1);
let cc: &str = std::str::from_utf8_unchecked(bytes);
println!("{cc}");
};
// Rust 衚çŸïŒãã€ãåïŒããæååã¹ã©ã€ã¹ãž
unsafe {
let ptr = rust_repr.0.as_ptr();
let bytes = std::slice::from_raw_parts(ptr, rust_repr.1);
let rust: &str = std::str::from_utf8_unchecked(bytes);
println!("{rust}");
};
äœè«: Rust ã«ã¯ c ãã¬ãã£ãã¯ã¹ä»ãã®æååãªãã©ã«ããããŸããããã¯æ«å°Ÿã« null ãã€ãã远å ããŸããããšãã° c"Rust" == b"Rust\0" ã§ãã
ç°ãªãã»ãã³ãã£ã¯ã¹
// Copyright 2026 Google LLC
// SPDX-License-Identifier: Apache-2.0
use std::ffi::{CStr, c_char};
use std::time::{SystemTime, SystemTimeError, UNIX_EPOCH};
unsafe extern "C" {
/// ã¿ã€ã ã¹ã¿ã³ã `t` ã«åºã¥ããŠãã©ãŒãããæžã¿ã®æå»ãäœæããã
fn ctime(t: *const libc::time_t) -> *const c_char;
}
fn now_formatted() -> Result<String, SystemTimeError> {
let now = SystemTime::now().duration_since(UNIX_EPOCH)?;
let seconds = now.as_secs() as i64;
// SAFETY: `seconds` ã¯ã·ã¹ãã ã¯ããã¯ã«ãã£ãŠçæãããããã
// ãªãŒããŒãããŒãåŒãèµ·ãããŸãã
let ptr = unsafe { ctime(&seconds) };
// SAFETY: ctime ã¯äºåã«ç¢ºä¿ãããïŒnull ã§ã¯ãªãïŒãããã¡ãžã®ãã€ã³ã¿ãè¿ããŸã
let ptr = unsafe { CStr::from_ptr(ptr) };
// SAFETY: ctime ã¯æå¹ãª UTF-8 ã䜿çšããŸã
let fmt = ptr.to_str().unwrap();
Ok(fmt.trim_end().to_string())
}
fn main() {
let t = now_formatted();
println!("{t:?}");
}
ä»ã®èšèªã§èš±å¯ãããŠããäžéšã®æ§æã¯ãRust èšèªã§ã¯è¡šçŸã§ããŸããã
ctime 颿°ã¯ãåŒã³åºãéã§å
±æãããå
éšãããã¡ã倿ŽããŸãããã㯠Rust ã®ã©ã€ãã¿ã€ã ã§ã¯è¡šçŸã§ããŸããã
'staticã¯é©çšãããŸãããã»ãã³ãã£ã¯ã¹ãç°ãªãããã§ã'aã¯é©çšãããŸããããããã¡ã¯ååŒã³åºãããé·ãçåããããã§ã
Rust â C
| èŠ³ç¹ | Rust | C |
|---|---|---|
| ãšã©ãŒ | Result<T, E>, Option<T> | ç¹å¥ãªæ»ãå€ãåºåãã©ã¡ãŒã¿ãã°ããŒãã« errno |
| æåå | &str/StringïŒUTF-8ãé·ããåããïŒ | ãã«çµç«¯ã® char*ããšã³ã³ãŒãã£ã³ã°ã¯æªå®çŸ© |
| ãã«èš±å®¹æ§ | Option<T> ã«ããæç€º | ã©ã®ãã€ã³ã¿ã null ã«ãªããã |
| æææš© | ã¢ãã£ã³åãã©ã€ãã¿ã€ã | æ £ç¿ |
| ã³ãŒã«ãã㯠| Fn/FnMut/FnOnce ã¯ããŒãžã£ | 颿°ãã€ã³ã¿ + void* userdata |
| ããã㯠| ã¹ã¿ãã¯ã¢ã³ã¯ã€ã³ãïŒãŸã㯠abortïŒ | abort |
ãšã©ãŒ: C ã®æ
£ç¿ã«åŸãããã« Result ã倿ããªããã°ãªããªããC åŽã§ã¯ ãšã©ãŒã®ç¢ºèªãå¿ããããã
æåå: 倿ã³ã¹ããããããRust ã®æååäžã®ãã«ãã€ãã¯åãè©°ããåŒãèµ·ããã å ¥åæã«ã¯ UTF-8 ã®æ€èšŒãå¿ èŠã
ãã«èš±å®¹æ§: Option<NonNull<T>> ãäœãã«ã¯ãC ããã®ãã¹ãŠã®ãã€ã³ã¿ãæ€æ» ããªããã°ãªãããunsafe ãããã¯ãŸãã¯å®è¡æã³ã¹ãã䌎ãã
æææš©: ãªããžã§ã¯ãã®ã©ã€ãã¿ã€ã ãæåã§ææžåããä¿èšŒããªããã°ãªããªãã
ã³ãŒã«ããã¯: ã¯ããŒãžã£ã fn ãã€ã³ã¿ + ã³ã³ããã¹ãã«åè§£ããªããã°ãªããªããã³ã³ããã¹ãã® ã©ã€ãã¿ã€ã ã¯æå管çãšãªãã
ãããã¯: FFI å¢çããŸãããããã¯ã¯æªå®çŸ©åäœã§ãããå¢çã§ catch_unwind ã«ãã£ãŠææããªããã°ãªããªãã
C++ â C
| èŠ³ç¹ | C | C++ |
|---|---|---|
| ãªãŒããŒããŒã | æå/ã¢ããã㯠| èªå |
| äŸå€ | - | ã¹ã¿ãã¯ã¢ã³ã¯ã€ã³ã |
| ãã¹ãã©ã¯ã¿ | æåã¯ãªãŒã³ã¢ãã | ãã¹ãã©ã¯ã¿ã«ããèªååŠçïŒRAIIïŒ |
| éPODå | - | ã³ã³ã¹ãã©ã¯ã¿ãvtableãä»®æ³åºåºãæã€ãªããžã§ã¯ã |
| ãã³ãã¬ãŒã | - | ã³ã³ãã€ã«æã³ãŒãçæ |
C++ ã«ã¯ãC ã«ã¯ååšãããFFI ã«åœ±é¿ãäžããæ©èœãããã€ããããŸã:
ãªãŒããŒããŒã: ååãã³ã°ãªã³ã°ã«ããããªãŒããŒããŒãã衚çŸããããšãäžå¯èœã«ãªããŸã
äŸå€: FFI å¢çã§äŸå€ãææãããšã©ãŒã³ãŒãã«å€æããªããã° ãªããŸãããextern "C" 颿°ããäŸå€ãå€ãžäŒæããããšã¯ æªå®çŸ©åäœãæ§æããããã§ã
ãã¹ãã©ã¯ã¿: C ã®åŒã³åºãåŽã¯ãã¹ãã©ã¯ã¿ãå®è¡ããªããããæç€ºç㪠*_destroy() 颿°ãå
¬éããªããã°ãªããŸãã
éPODå: 倿ž¡ãã¯æå³ããªããªããããFFI å¢çããŸããã§äžéæãã€ã³ã¿ãäœ¿çš ããªããã°ãªããŸãã
ãã³ãã¬ãŒã: çŽæ¥å ¬éããããšã¯ã§ããŸãããæç€ºçã«ã€ã³ã¹ã¿ã³ã¹åããå ç¹æ®åãã©ããããå¿ èŠããããŸã
Rust â C++
| èŠ³ç¹ | Rust | C++ |
|---|---|---|
| ããªãã¢ã«åé 眮å¯èœæ§ | ãã¹ãŠã®ã ãŒã㯠memcpy | èªå·±åç §åãã ãŒãã³ã³ã¹ãã©ã¯ã¿ã«ã¯å¯äœçšãããåŸã |
| ç Žæ£ã®å®å šæ§ | å
ã®å Žæã§ã®ã¿ Drop::drop() ãåŒã°ãã | ã ãŒãåŸã®ãªããžã§ã¯ãã«å¯ŸããŠãã¹ãã©ã¯ã¿ãå®è¡ãããå Žåããã |
| äŸå€å®å šæ§ | panicïŒabort ãŸã㯠unwindïŒ | äŸå€ïŒunwindïŒ |
| ABI ã®å®å®æ§ | æç€ºçã«äžå®å® | ãã³ããŒäŸå |
C ãä»ããçžäºéçšãé¿ããããšãã§ãããšããŠããFFI ã«åœ±é¿ããèšèªäžã®é åãããã€ããããŸãïŒ
ããªãã¢ã«åé 眮å¯èœæ§
Rust åŽã§ C++ ãªããžã§ã¯ããå®å šã«ã ãŒãããããšã¯ã§ããŸãããpin ããããC++ ããŒãäžã«ä¿æããå¿ èŠããããŸãã
Rust ã§ã¯ãä»£å ¥æã倿ž¡ãæã«çºçãããªããžã§ã¯ãã®ã ãŒãã¯ãåžžã«å€ããããåäœã§ã³ããŒããŸãã
C++ ã§ã¯ãä»£å ¥æŒç®åã®ãªãŒããŒããŒããã ãŒãã³ã³ã¹ãã©ã¯ã¿ãã³ããŒã³ã³ã¹ãã©ã¯ã¿ã®äœæãèš±å¯ããããšã§ããŠãŒã¶ãŒãç¬èªã®ã»ãã³ãã£ã¯ã¹ãå®çŸ©ã§ããŸãã
ããã¯çžäºéçšã«åœ±é¿ããŸãã髿§èœãª C++ ã§ã¯èªå·±åç §åãèªç¶ã«çŸããããã§ããã«ã¹ã¿ã ã³ã³ã¹ãã©ã¯ã¿ã¯ããªããžã§ã¯ããã¡ã¢ãªå ã§äœçœ®ãç§»åããŠããå®å šæ§ã®äžå€æ¡ä»¶ãç¶æã§ããŸãã
åãã»ãã³ãã£ã¯ã¹ãæã€ãªããžã§ã¯ãã Rust ã§å®çŸ©ããããšã¯äžå¯èœã§ãã
ç Žæ£ã®å®å šæ§
ã ãŒãåŸã® C++ ãªããžã§ã¯ãã®ã»ãã³ãã£ã¯ã¹ã¯å¯Ÿå¿ä»ããããªããããRust ã C++ åããã ãŒããããªãããã«é²ãå¿ èŠããããŸãã
äŸå€å®å šæ§
ã©ã¡ããå®å šã«çžæåŽãžãŸããã£ãŠæž¡ãããšã¯ã§ããªããããäž¡æ¹ãšãå¢çã§ææããå¿ èŠããããŸãã
abs(3) ãã©ãããã
// Copyright 2026 Google LLC
// SPDX-License-Identifier: Apache-2.0
fn abs(x: i32) -> i32;
fn main() {
let x = -42;
let abs_x = abs(x);
println!("{x}, {abs_x}");
}
ãã®ã¹ã©ã€ãã§ã¯ãã©ãããŒãæžãããã®ãã¿ãŒã³ã確ç«ããŸãã
颿°ã·ã°ããã£ã®å€éšå®çŸ©ãèŠã€ãã äžèŽãã颿°ã Rust ã® extern ãããã¯å
ã« æžã æºããã¹ãå®å
šæ§äžå€æ¡ä»¶ãäœãã確èªãã ãã®é¢æ°ãå®å
šãšããŠããŒã¯ ã§ãããã©ããã倿ãã
ããã ãŸã åäœããªãããšã«æ³šæããŠãã ããã
extern ãããã¯ã远å ããŸã:
#![allow(unused)] fn main() { // Copyright 2026 Google LLC // SPDX-License-Identifier: Apache-2.0 unsafe extern "C" { fn abs(x: i32) -> i32; } }
å€ãã® POSIX 颿°ã Rust ã§å©çšã§ããã®ã¯ãCargo ãããã©ã«ãã§ C æšæºã©ã€ãã©ãª ïŒlibcïŒã«ãªã³ã¯ãããã®ã·ã³ãã«ãããã°ã©ã ã®ã¹ã³ãŒãã«åã蟌ãŸããããã§ãã ããšã説æããŸãã
ã¿ãŒããã«ã§ man 3 abs ãŸã㯠ãŠã§ãããŒãž ã衚瀺ããŸãã
颿°ã·ã°ããã£ã¯ãã®å®çŸ©ãšäžèŽããŠããªããã°ãªããªãããšã説æããŸã: int abs(int j);ã
ã³ãŒããããã¯ãæŽæ°ã㊠C ã®åã䜿ããŸãã
#![allow(unused)] fn main() { // Copyright 2026 Google LLC // SPDX-License-Identifier: Apache-2.0 use std::ffi::c_int; unsafe extern "C" { fn abs(x: c_int) -> c_int; } }
çç±ã説æããŸã: ffi::c_int ã䜿ããšãã³ãŒãã®ç§»æ€æ§ãåäžããŸãã æšæºã©ã€ãã©ãªãã¿ãŒã²ãããã©ãããã©ãŒã åãã«ã³ã³ãã€ã«ããããšãããããå¹
㯠ãã®ãã©ãããã©ãŒã ã«å¿ããŠæ±ºå®ãããŸããC æšæºã«ããã°ãc_int ã¯ãããäžè¬ç㪠i32 ã§ã¯ãªã i16 ãšããŠå®çŸ©ãããå ŽåããããŸãã
ïŒä»»æïŒc_int ã®ããã¥ã¡ã³ã ã衚瀺ããããã i32 ã®åãšã€ãªã¢ã¹ã§ããããš ã瀺ããŸãã
ã³ã³ãã€ã«ã詊ã¿ãŠããerror: extern blocks must be unsafeããšãããšã©ãŒ ã¡ãã»ãŒãžã衚瀺ãããŸãã
ãããã¯ã« unsafe ããŒã¯ãŒãã远å ããŸã:
#![allow(unused)] fn main() { // Copyright 2026 Google LLC // SPDX-License-Identifier: Apache-2.0 use std::ffi::c_int; unsafe extern "C" { fn abs(x: c_int) -> c_int; } }
åŠç¿è ããã®å€æŽã®éèŠæ§ãçè§£ããŠããããšã確èªããŸããåå®å šæ§ããã®ä»ã® å®å šæ§ã®åææ¡ä»¶ãå®ãå¿ èŠããããŸãã
åã³ã³ãã€ã«ããŸãã
abs 颿°ã« safe ããŒã¯ãŒãã远å ããŸã:
#![allow(unused)] fn main() { // Copyright 2026 Google LLC // SPDX-License-Identifier: Apache-2.0 use std::ffi::c_int; unsafe extern "C" { safe fn abs(x: c_int) -> c_int; } }
safe fn ã¯ãunsafe ãããã¯ãªãã§ abs ãå®å
šã«åŒã³åºããããšã瀺ã ãã®ã ãšèª¬æããŸãã
åèçšã®å®æçããã°ã©ã :
// Copyright 2026 Google LLC // SPDX-License-Identifier: Apache-2.0 use std::ffi::c_int; unsafe extern "C" { safe fn abs(x: c_int) -> c_int; } fn main() { let x = -42; let abs_x = abs(x); println!("{x}, {abs_x}"); }
srand(3) ãš rand(3) ã®ã©ãã
// Copyright 2026 Google LLC
// SPDX-License-Identifier: Apache-2.0
use libc::{rand, srand};
// unsafe extern "C" {
// /// ä¹±æ°çæåšãã·ãŒããã
// fn srand(seed: std::ffi::c_uint);
// fn rand() -> std::ffi::c_int;
// }
fn main() {
unsafe { srand(12345) };
let a = unsafe { rand() as i32 };
println!("{a:?}");
}
ãã®ã¹ã©ã€ãã§ã¯ãã©ãããŒã誀ã£ãŠæžãããŠãããšãããã«ç°¡åã« æªå®çŸ©åäœãåŒãèµ·ãããŠããŸããã瀺ãããšããŠããŸããåå®å šæ§ã®åé¡ã ã©ãã»ã©ç°¡åã«åŒãèµ·ãããããèŠãŠãããŸãã
rand 颿°ãš srand 颿°ã¯ãC æšæºã©ã€ãã©ãª (libc) ã«ãã£ãŠæäŸãããŠããããšã説æããŸãã
ãããã®é¢æ°ã¯ libc ã¯ã¬ãŒãããå ¬éãããŠããŸããããããã«å¯Ÿãã FFI ã©ãããŒãæäœæ¥ã§æžãããšãã§ãããšèª¬æããŸãã
å ¬éããã颿°ãåŒã³åºãäŸã瀺ããŸãã
Rust ããã°ã©ã ã«ã¯ããã©ã«ãã§ libc ããªã³ã¯ããããããã³ãŒãã¯ã³ã³ãã€ã«ã§ããŸãã
ééã£ãåã䜿ã£ãŠããRust ã¯ãããä¿¡ããŠããŸãããšã説æããŸãã
fn rand() -> std::ffi::c_int; ã char ãè¿ãããã«å€æŽããŸãã
åå®å šæ§ã®åé¡ãé¿ããããšã¯ãã©ãããŒãæäœæ¥ã§æžãã®ã§ã¯ãªãã çæããŒã«ã䜿ãçç±ã® 1 ã€ã§ãã
C ã©ã€ãã©ãªã®äŸ
#ifndef TEXT_ANALYSIS_H
#define TEXT_ANALYSIS_H
#include <stddef.h>
#include <stdbool.h>
typedef struct TextAnalyst TextAnalyst;
typedef struct {
const char* start;
size_t length;
size_t index;
} Token;
typedef enum {
TA_OK = 0,
TA_ERR_NULL_POINTER,
TA_ERR_OUT_OF_MEMORY,
TA_ERR_OTHER,
} TAError;
/* ããŒã¯ã³ãèŠã€ãããªãã£ãããšã瀺ãã«ã¯ `false` ãè¿ããŸãã */
typedef bool (*Tokenizer)(Token* token, void* extra_context);
typedef bool (*TokenCallback)(void* user_context, Token* token, void* result);
/* TextAnalyst ã³ã³ã¹ãã©ã¯ã¿ãŒ */
TextAnalyst* ta_new(void);
/* TextAnalyst ãã¹ãã©ã¯ã¿ãŒ */
void ta_free(TextAnalyst* ta);
/* çŸåšã®ããã¥ã¡ã³ããã¯ãªã¢ããããã«ç¶æ
ããªã»ããããŸã */
void ta_reset(TextAnalyst* ta);
/* ã«ã¹ã¿ã ããŒã¯ãã€ã¶ãŒã䜿çšããŸãïŒããã©ã«ãã¯ç©ºçœæåïŒ */
void ta_set_tokenizer(TextAnalyst* ta, Tokenizer* func);
TAError ta_set_text(TextAnalyst* ta, const char* text, size_t len, bool make_copy);
/* åããŒã¯ã³ã« `callback` ãé©çšããŸã */
size_t ta_foreach_token(const TextAnalyst* ta, const TokenCallback* callback, void* user_context);
/* 人éãèªãããšã©ãŒã¡ãã»ãŒãžãååŸããŸã */
const char* ta_error_string(TAError error);
#endif /* TEXT_ANALYSIS_H */
C ã©ã€ãã©ãªã¯ãvoid* åŒæ°ã䜿ã£ãŠå®è£
ã®è©³çްãé ããŸãã
TextAnalyst åãš Analysis åãé ãèªç¶èšèªåŠçã©ã€ãã©ãªã®ããã®ããããŒãã¡ã€ã«ãèããŠã¿ãŸãããã
ããã¯ãRust ã§ã¯æ¬¡ã®ãããªåã§ãšãã¥ã¬ãŒãã§ããŸãã
#![allow(unused)] fn main() { // Copyright 2026 Google LLC // SPDX-License-Identifier: Apache-2.0 #[repr(C)] pub struct TextAnalyst { _private: [u8; 0], } }
æŒç¿: åŠç¿è ã«ãã®ã©ã€ãã©ãªãã©ããããŠããã£ãŠãã ããã
è§£çäŸ
#![allow(unused)] fn main() { // Copyright 2026 Google LLC // SPDX-License-Identifier: Apache-2.0 // ffi.rs use std::ffi::c_char; use std::os::raw::c_void; #[repr(C)] pub struct TextAnalyst { _private: [u8; 0], } #[repr(C)] #[derive(Debug, Clone, Copy)] pub struct Token { pub start: *const c_char, pub length: usize, pub index: usize, } #[repr(C)] #[derive(Debug, Clone, Copy, PartialEq, Eq)] pub enum TAError { Ok = 0, NullPointer = 1, OutOfMemory = 2, Other = 3, } pub type Tokenizer = Option< unsafe extern "C" fn(token: *mut Token, extra_context: *mut c_void) -> bool, >; pub type TokenCallback = Option< unsafe extern "C" fn( user_context: *mut c_void, token: *mut Token, result: *mut c_void, ) -> bool, >; unsafe extern "C" { pub fn ta_new() -> *mut TextAnalyst; pub fn ta_free(ta: *mut TextAnalyst); pub fn ta_reset(ta: *mut TextAnalyst); pub fn ta_set_tokenizer(ta: *mut TextAnalyst, func: *const Tokenizer); pub fn ta_set_text( ta: *mut TextAnalyst, text: *const c_char, len: usize, make_copy: bool, ) -> TAError; pub fn ta_foreach_token( ta: *const TextAnalyst, callback: *const TokenCallback, user_context: *mut c_void, ) -> usize; pub fn ta_error_string(error: TAError) -> *const c_char; } }
äŸ: æååã€ã³ã¿ãŒãã³ã°ã©ã€ãã©ãª
C++ ããããŒ: interner.hpp
#ifndef INTERNER_HPP
#define INTERNER_HPP
#include <string>
#include <unordered_set>
class StringInterner {
std::unordered_set<std::string> strings;
public:
// ã€ã³ã¿ãŒã³åãããæååãžã®ãã€ã³ã¿ãè¿ãïŒinterner ã®åç¶æéäžã¯æå¹ïŒ
const char* intern(const char* s) {
auto [it, _] = strings.emplace(s);
return it->c_str();
}
size_t count() const {
return strings.size();
}
};
#endif
C ããããŒãã¡ã€ã«: interner.h
// interner.hïŒFFI çšã® C APIïŒ
#ifndef INTERNER_H
#define INTERNER_H
#include <stddef.h>
#ifdef __cplusplus
extern "C" {
#endif
typedef struct StringInterner StringInterner;
StringInterner* interner_new(void);
void interner_free(StringInterner* interner);
const char* interner_intern(StringInterner* interner, const char* s);
size_t interner_count(const StringInterner* interner);
#ifdef __cplusplus
}
#endif
C++ å®è£ ïŒinterner.cppïŒ
#include "interner.hpp"
#include "interner.h"
extern "C" {
StringInterner* interner_new(void) {
return new StringInterner();
}
void interner_free(StringInterner* interner) {
delete interner;
}
const char* interner_intern(StringInterner* interner, const char* s) {
return interner->intern(s);
}
size_t interner_count(const StringInterner* interner) {
return interner->count();
}
}
ããã¯å°ã倧ããã®äŸã§ããæååã€ã³ã¿ãŒããŒã®ã©ãããŒãæžããŠãã ãããäžéæãã€ã³ã¿ã®äœææ¹æ³ã«ã€ããŠã¯ã以äžã®ã³ãŒãã説æããŠçŽæ¥ç€ºããããããã¯åŠç¿è ã«è¿œå ã§èª¿ã¹ãŠãããå¿ èŠããããŸãã
æšå¥šãããè§£ç
#![allow(unused)] fn main() { // Copyright 2026 Google LLC // SPDX-License-Identifier: Apache-2.0 use std::ffi::{CStr, CString}; use std::marker::PhantomData; use std::os::raw::c_char; #[repr(C)] pub struct StringInternerRaw { _opaque: [u8; 0], _pin: PhantomData<(*mut u8, std::marker::PhantomPinned)>, } unsafe extern "C" { fn interner_new() -> *mut StringInternerRaw; fn interner_free(interner: *mut StringInternerRaw); fn interner_intern( interner: *mut StringInternerRaw, s: *const c_char, ) -> *const c_char; fn interner_count(interner: *const StringInternerRaw) -> usize; } }
raw ã©ãããŒãæžããããæ¬¡ã«åŠç¿è ã«å®å šãªã©ãããŒãäœæããŠããã£ãŠãã ããã
ããããšãããããŸããïŒ
Comprehensive Rust ðŠ ãåè¬ããŠããã ããããããšãããããŸãïŒ æ¥œããã§ããã ããŠãããã 圹ã«ç«ã€ãã®ã§ãã£ããªã幞ãã§ãã
ç§ãã¡ãããã®ã³ãŒã¹ããŸãšãäžããäœæ¥ã楜ãã¿ãŸãããã³ãŒã¹ã¯å®ç§ã§ã¯ãªãããã 誀ããèŠã€ãããæ¹åã®ã¢ã€ãã¢ããã£ããããå Žåã¯ããã² GitHub ã§ãé£çµ¡ãã ããã ã¿ãªããŸããã®å£°ããã²ãèãããã ããã
- ã¹ããŒã«ãŒããŒããèªãã§ããã ããããããšãããããŸãïŒ åœ¹ã«ç«ã£ãŠãããªã幞ãã§ããããŒãã®ãªã ããŒãžãèŠã€ããå Žåã¯ãPR ãéã£ãŠ issue #1083 ã«ãªã³ã¯ããŠãã ãããæ¢åã®ããŒããžã® ä¿®æ£ãæ¹åã«ã€ããŠããç§ãã¡ã¯å€§å€æè¬ããŠããŸãã
çšèªé
以äžã¯ãå€ãã® Rust çšèªã«çãå®çŸ©ãäžããããšãç®çãšããçšèªéã§ãã翻蚳ã«ãããŠã¯ãããã«ããçšèªã è±èªã®åèªã«çµã³ä»ãã圹å²ãæãããŸãã
- å²ãåœãŠ:
ããŒãäžã§ã®åçã¡ã¢ãªå²ãåœãŠã - é
å:
ã¡ã¢ãªå ã«é£ç¶ããŠæ ŒçŽããããåãåã®èŠçŽ ãããªãåºå®ãµã€ãºã® ã³ã¬ã¯ã·ã§ã³ãåç §: é åã - é¢é£å:
ç¹å®ã®ãã¬ã€ãã«é¢é£ä»ããããåãåå士ã®é¢ä¿ãå®çŸ©ããã®ã« 圹ç«ã¡ãŸãã - ãã¢ã¡ã¿ã« Rust:
äœã¬ãã«ãª Rust éçºãå€ãã®å Žåããªãã¬ãŒãã£ã³ã°ã·ã¹ãã ã®ãªã ã·ã¹ãã ã«ãããã€ãããŸããåç §: ãã¢ã¡ã¿ã« Rustã - ãããã¯:
ããã㯠㚠ã¹ã³ãŒã ãåç §ããŠãã ããã - åçš:
åçš ãåç §ããŠãã ããã - åçšãã§ãã«ãŒ:
ãã¹ãŠã® åçš ãæå¹ã§ããããšãæ€æ»ãããRust ã³ã³ãã€ã©ã®äžéšã - ãã¬ãŒã¹:
{ãš}ãæ³¢æ¬åŒ§ ãšãåŒã°ããããã㯠ãåºåããŸãã - ãã£ãã«:
ã¡ãã»ãŒãžãå®å šã«ã¹ã¬ããéã§åãæž¡ããã㫠䜿çšãããŸãã - äžŠè¡æ§:
è€æ°ã®ã¿ã¹ã¯ãŸãã¯ããã»ã¹ãåæã«å®è¡ããããšãåç §: Rust ã®äžŠè¡æ§ãžããããã - 宿°:
ããã°ã©ã ã®å®è¡äžã«å€åããªãå€ãåç §: constã - å¶åŸ¡ãããŒ:
ããã°ã©ã å ã§åã ã®æãåœä»€ãå®è¡ããã é åºãåç §: å¶åŸ¡ãããŒã®åºæ¬ã - ã¯ã©ãã·ã¥:
ããã°ã©ã ã®äºæããªããåŠçãããŠããªãé害ãŸãã¯çµäºãåç §: panicã - åæå:
è€æ°ã®ååä»ã宿°ã®ãããã 1 ã€ãä¿æããããŒã¿åã§ãé¢é£ä»ãããã ã¿ãã«ãŸãã¯æ§é äœã䌎ãå ŽåããããŸããåç §: enumã - ãšã©ãŒ:
æåŸ ãããåäœããå€ãããäºæããªãç¶æ ãŸãã¯çµæã åç §: ãšã©ãŒåŠçã - ãšã©ãŒåŠç:
ããã°ã©ã å®è¡äžã«çºçãã ãšã©ãŒ ã管çãããã㫠察å¿ããããã»ã¹ã - 颿°:
ç¹å®ã®ã¿ã¹ã¯ãå®è¡ãããåå©çšå¯èœãªã³ãŒãã®ãããã¯ãåç §: 颿°ã - ã¬ããŒãžã³ã¬ã¯ã¿:
ãã¯ã䜿çšãããŠããªããªããžã§ã¯ããå æããŠããã¡ã¢ãªãèªåçã« è§£æŸããä»çµã¿ãåç §: ã¡ã¢ãªç®¡çãžã®ã¢ãããŒãã - ãžã§ããªã¯ã¹:
åã®ãã¬ãŒã¹ãã«ããŒã䜿ã£ãŠã³ãŒããæžããããã«ããæ©èœã§ãç°ãªã ããŒã¿åã«å¯ŸããŠã³ãŒããåå©çšã§ããŸããåç §: ãžã§ããªã¯ã¹ã - äžå€:
äœæåŸã«å€æŽã§ããªãããšãåç §: 倿°ã - çµåãã¹ã:
ã·ã¹ãã ã®ç°ãªãéšåã ã³ã³ããŒãã³ãéã®çžäºäœçšãæ€èšŒããçš®é¡ã®ãã¹ããåç §: ãã®ä»ã®çš®é¡ã®ãã¹ãã - ã©ã€ãã©ãª:
ããã°ã©ã ããå©çšã§ãããäºåã«ã³ã³ãã€ã«ãããã«ãŒãã³ãã³ãŒãã®éåãåç §: ã¢ãžã¥ãŒã«ã - ãã¯ã:
Rust ã® ãã¯ã ã¯ãååã«!ãä»ããŠããããšã§ èŠåããããŸãããã¯ãã¯éåžžã®é¢æ°ã§ã¯äžååãªå Žåã«äœ¿ãããŸããå žåçãªäŸ ã¯format!ã§ãããã¯å¯å€åã®åŒæ°ãåãåããŸããããã㯠Rust ã®é¢æ°ã§ã¯ãµããŒããããŠããŸããã main颿°:
Rust ããã°ã©ã ã¯main颿° ããå®è¡ãéå§ããŸãã- match:
åŒã®å€ã«å¯Ÿã㊠ãã¿ãŒã³ãããã³ã° ãè¡ãã Rust ã®å¶åŸ¡ãããŒæ§æã - ã¡ã¢ãªãªãŒã¯:
ããã°ã©ã ãäžèŠã«ãªã£ãã¡ã¢ãªãè§£æŸã§ããã ãã®çµæãšããŠã¡ã¢ãªäœ¿çšéãåŸã ã«å¢å ããŠããç¶æ³ãåç §: ã¡ã¢ãªç®¡çãžã®ã¢ãããŒãã - ã¡ãœãã:
Rust ã®ãªããžã§ã¯ããŸãã¯åã«é¢é£ä»ãããã颿°ãåç §: ã¡ãœããã - ã¢ãžã¥ãŒã«:
颿°ãåããã¬ã€ããªã©ã®å®çŸ©ãå«ãåå空éã§ã Rust ã§ã³ãŒããæŽçããããã«äœ¿ãããŸããåç §: ã¢ãžã¥ãŒã«ã - ã ãŒã:
Rust ã«ãããŠããã倿°ããå¥ã®å€æ°ãžå€ã®æææš©ãç§»ãããšãåç §: ã ãŒãã»ãã³ãã£ã¯ã¹ã - å¯å€:
宣èšåŸã« 倿° ã 倿Žã§ãã Rust ã®æ§è³ªã - æææš©:
å€ã«é¢é£ä»ããããã¡ã¢ãªã®ç®¡çãã³ãŒãã®ã©ã®éšåãæ ãããå®çŸ©ããã Rust ã®æŠå¿µãåç §: æææš©ã - ãããã¯:
Rust ã«ãããå埩äžèœãªãšã©ãŒç¶æ ã§ãããã°ã©ã ã®çµäºã åŒãèµ·ãããŸããåç §: ãããã¯ã - ãã¿ãŒã³:
å€ããªãã©ã«ããŸãã¯æ§é ã®çµã¿åããã§ãRust ã«ãã㊠åŒã«å¯ŸããŠããããããããšãã§ããŸããåç §: ãã¿ãŒã³ãããã³ã°ã - ãã€ããŒã:
ã¡ãã»ãŒãžãã€ãã³ãããŸãã¯ããŒã¿æ§é ã«ãã£ãŠéã°ããããŒã¿ãŸãã¯æ å ±ã - ã¬ã·ãŒã:
Rust ã® ã¡ãœãã ã«ãããæåã®ãã©ã¡ãŒã¿ã§ã ãã®ã¡ãœãããåŒã³åºãããã€ã³ã¹ã¿ã³ã¹ã衚ããŸãã - åç
§:
æææš©ãç§»ããã«å€ãåçšãããéææã®ãã€ã³ã¿ã åç §ã¯ å ±æïŒäžå€ïŒ ãŸã㯠æä»çïŒå¯å€ïŒ ã®ããããã§ãã - åç
§ã«ãŠã³ã:
ãªããžã§ã¯ããžã®åç §æ°ã远跡ãã ã«ãŠã³ãããŒãã«éãããšãã«ãã®ãªããžã§ã¯ããè§£æŸããã¡ã¢ãªç®¡çææ³ãåç §: Rcã - Rust:
å®å šæ§ãããã©ãŒãã³ã¹ã äžŠè¡æ§ãéèŠããã·ã¹ãã ããã°ã©ãã³ã°èšèªãåç §: Rust ãšã¯äœãïŒã - å®å
š:
Rust ã®æææš©ãšåçšã®èŠåã«åŸãã³ãŒããæãã ã¡ã¢ãªé¢é£ã®ãšã©ãŒãé²ããŸããåç §: Unsafe Rustã - ã¹ã©ã€ã¹:
é åã ãã¯ã¿ã®ãããªé£ç¶ããã·ãŒã±ã³ã¹ãžã®ãåçãµã€ãºã®ãã¥ãŒãé åãšã¯ç°ãªããã¹ã©ã€ã¹ã®ãµã€ãºã¯å®è¡æã«æ±ºå®ãããŸããåç §: ã¹ã©ã€ã¹ã - ã¹ã³ãŒã:
倿°ãæå¹ã§äœ¿çšã§ãããããã°ã©ã å ã®é åãåç §: ãããã¯ãšã¹ã³ãŒãã - æšæºã©ã€ãã©ãª:
Rust ã«ãããŠäžå¯æ¬ ãªæ©èœãæäŸããã¢ãžã¥ãŒã«ã®éåãåç §: æšæºã©ã€ãã©ãªã - static:
éç倿°ããŸãã¯'staticã©ã€ãã¿ã€ã ãæã€é ç®ãå®çŸ©ããããã«äœ¿çšããã Rust ã®ããŒã¯ãŒããåç §: staticã - æåå:
ããã¹ãããŒã¿ãæ ŒçŽããããŒã¿åãåç §: æååã - æ§é äœ:
ç°ãªã åã®å€æ°ã 1 ã€ã®ååã®äžã«ãŸãšãããRust ã®è€åããŒã¿åãåç §: æ§é äœã - ãã¹ã:
ã»ãã®ã³ãŒãã®æ£ãããæ€èšŒãã颿°ãRust ã«ã¯çµã¿èŸŒã¿ã®ãã¹ã ã©ã³ããŒããããŸããåç §: ãã¹ãã - ã¹ã¬ãã:
ããã°ã©ã å ã®ç¬ç«ããå®è¡ã®æµãã§ã䞊è¡å®è¡ãå¯èœã«ããŸãã åç §: ã¹ã¬ããã - ã¹ã¬ããå®å
šæ§:
ãã«ãã¹ã¬ãã ç°å¢ã§æ£ããåäœãä¿èšŒããããã°ã©ã ã®æ§è³ªãåç §: Send ãš Syncã - ãã¬ã€ã:
æªç¥ã®åã«å¯ŸããŠå®çŸ©ãããã¡ãœããã®éåã§ã Rust ã«ãããŠå€çžæ§ãå®çŸããæ¹æ³ãæäŸããŸããåç §: ãã¬ã€ãã - ãã¬ã€ãå¢ç:
é¢å¿ã®ããããã€ãã®ãã¬ã€ããåã«å®è£ ãããã èŠæ±ã§ããæœè±¡åãåç §: ãã¬ã€ãå¢çã - ã¿ãã«:
ç°ãªãåã®å€æ°ãå«ãè€åããŒã¿åãã¿ãã«ã®ãã£ãŒã«ã ã«ã¯ååããªããåºæ°ã«ãã£ãŠã¢ã¯ã»ã¹ãããŸããåç §: ã¿ãã«ã - å:
Rust ã«ãããŠãç¹å®ã®çš®é¡ã®å€ã«å¯ŸããŠã©ã®æäœãå®è¡ã§ããããå®ããåé¡ã åç §: åãšå€ã - åæšè«:
倿°ãŸã㯠åŒã®åã Rust ã³ã³ãã€ã©ãæšè«ããèœåãåç §: åæšè«ã - æªå®çŸ©åäœ:
Rust ã«ãããŠçµæãèŠå®ãããŠããªãåäœãŸãã¯ç¶æ ã§ãå€ãã®å Žå äºæž¬äžèœãªããã°ã©ã åäœã«ã€ãªãããŸããåç §: Unsafe Rustã - å
±çšäœ:
ç°ãªãåã®å€ãä¿æã§ããããŒã¿åã§ãããäžåºŠã«ä¿æã§ããã®ã¯ 1 ã€ã ãã§ãã åç §: å ±çšäœã - åäœãã¹ã:
Rust ã«ã¯ãå°ããªåäœãã¹ããšãã倧ã㪠çµåãã¹ããå®è¡ããããã®çµã¿èŸŒã¿ãµããŒãããããŸããåç §: åäœãã¹ãã - ãŠãããå:
ããŒã¿ãæããªãåã§ãã¡ã³ãã®ãªãã¿ãã«ãšããŠèšè¿°ãããŸããåç §: 颿° ã®ã¹ããŒã«ãŒããŒãã - unsafe:
æªå®çŸ©åäœ ãåŒãèµ·ããã Rust ã®ãµãã»ãããåç §: Unsafe Rustã - 倿°:
ããŒã¿ãæ ŒçŽããã¡ã¢ãªäžã®äœçœ®ã倿°ã¯ ã¹ã³ãŒã å ã§æå¹ã§ããåç §: 倿°ã
ãã®ä»ã® Rust ãªãœãŒã¹
Rust ã³ãã¥ããã£ã¯ãé«å質ã§ç¡æã®ãªã³ã©ã€ã³ãªãœãŒã¹ãæ°å€ã äœæããŠããŸãã
å ¬åŒããã¥ã¡ã³ã
Rust ãããžã§ã¯ãã¯å€ãã®ãªãœãŒã¹ãå ¬éããŠããŸããããã㯠Rust å šè¬ã æ±ã£ãŠããŸãã
- The Rust Programming Language: Rust ã«é¢ãã å®çªã®ç¡ææžç±ã§ããèšèªã詳ããæ±ã£ãŠãããå®éã«äœããªããåŠã¹ã ããã€ãã®ãããžã§ã¯ããå«ãŸããŠããŸãã
- Rust By Example: ããŸããŸãªæ§æèŠçŽ ã 瀺ãäžé£ã®äŸãéããŠãRust ã®æ§æãæ±ã£ãŠããŸããäŸã®ã³ãŒããçºå±ããã ããšãæ±ããããå°ããªæŒç¿ãå«ãŸããããšããããŸãã
- Rust Standard Library: Rust ã®æšæºã©ã€ãã©ãªã® å®å šãªããã¥ã¡ã³ãã§ãã
- The Rust Reference: Rust ã®ææ³ãš ã¡ã¢ãªã¢ãã«ã説æãããæªå®æã®æžç±ã§ãã
- Rust API Guidelines: API ã®èšè𿹿³ã«é¢ããæšå¥šäºé ã§ãã
å ¬åŒã® Rust ãµã€ãã§å ¬éãããŠãããããå°éçãªã¬ã€ã:
- The Rustonomicon: çã®ãã€ã³ã¿ã®æ±ãã ä»èšèªãšã®é£æºïŒFFIïŒãå«ããunsafe Rust ãæ±ã£ãŠããŸãã
- Asynchronous Programming in Rust: Rust Book ã®å·çåŸã«å°å ¥ããããæ°ããéåæããã°ã©ãã³ã°ã¢ãã«ã æ±ã£ãŠããŸãã
- The Embedded Rust Book: ãªãã¬ãŒãã£ã³ã°ã·ã¹ãã ã®ãªãçµã¿èŸŒã¿ããã€ã¹ã§ Rust ã䜿ãããã® å ¥éæžã§ãã
éå ¬åŒã®åŠç¿è³æ
Rust ã«é¢ãããã®ä»ã®ã¬ã€ãããã¥ãŒããªã¢ã«ã®äžéš:
- Learn Rust the Dangerous Way: äœã¬ãã«ãª C ããã°ã©ããŒã®èŠç¹ãã Rust ãæ±ã£ãŠããŸãã
- Rust for Embedded C Programmers: C ã§ãã¡ãŒã ãŠã§ã¢ãæžãéçºè ã®èŠç¹ãã Rust ãæ±ã£ãŠããŸãã
- Rust for professionals: CãC++ãJavaãJavaScriptãPython ãªã©ã®ä»èšèªãšã®æ¯èŒã䞊ã¹ãŠç€ºããªããã Rust ã®æ§æãæ±ã£ãŠããŸãã
- Rust on Exercism: Rust ã®åŠç¿ã«åœ¹ç«ã€ 100 以äžã®æŒç¿ã§ãã
- Ferrous Teaching Material: Rust èšèªã®åºæ¬çãªéšåãšé«åºŠãªéšåã®äž¡æ¹ãæ±ããäžé£ã®çã ãã¬ãŒã³ããŒã·ã§ã³ã§ããWebAssembly ã async/await ãªã©ã®ã»ãã® ãããã¯ãæ±ãããŠããŸãã
- Advanced testing for Rust applications: Rust çµã¿èŸŒã¿ã®ãã¹ããã¬ãŒã ã¯ãŒã¯ã®ç¯å²ãè¶
ãããèªåã®ããŒã¹ã§é²ãããã ã¯ãŒã¯ã·ã§ããã§ãã
googletestãã¹ãããã·ã§ãããã¹ããã¢ãã¯ã«å ãã ç¬èªã®ã«ã¹ã¿ã ãã¹ãããŒãã¹ã®æžãæ¹ãæ±ã£ãŠããŸãã - Beginnerâs Series to Rust ãš Take your first steps with Rust: æ°ããéçºè åãã® 2 ã€ã® Rust ã¬ã€ãã§ããåè 㯠35 æ¬ã®åç»ã»ããã§ã åŸè 㯠Rust ã®æ§æãšåºæ¬çãªæ§æèŠçŽ ãæ±ã 11 åã®ã¢ãžã¥ãŒã«ã®ã»ããã§ãã
- Learn Rust With Entirely Too Many Linked Lists: ããã€ãã®ç°ãªã çš®é¡ã®ãªã¹ãæ§é ãå®è£ ããªãããRust ã®ã¡ã¢ãªç®¡çã«ãŒã«ãæ·±ãæãäžã㊠ããŸãã
- The Little Book of Rust Macros: å®è·µç㪠äŸãšãšãã«ãRust ãã¯ãã®å€ãã®è©³çŽ°ãæ±ã£ãŠããŸãã
ããã«å€ãã® Rust æžç±ã«ã€ããŠã¯ãLittle Book of Rust Books ã åç §ããŠãã ããã
ã¯ã¬ãžãã
ããã«ããè³æã¯ãå€ãã®åªãã Rust ããã¥ã¡ã³ãã®ãœãŒã¹ãåºã«ããŠã ãŸããæçšãªãªãœãŒã¹ã®å®å šãªäžèЧã«ã€ããŠã¯ããã®ä»ã®ãªãœãŒ ã¹ ã®ããŒãžãåç §ããŠãã ããã
Comprehensive Rust ã®è³æã¯ Apache 2.0 ã©ã€ã»ã³ã¹ã®æ¡ä»¶ã«åºã¥ã㊠ã©ã€ã»ã³ã¹ãããŠããŸãã詳现ã«ã€ããŠã¯ LICENSE ãåç
§ã㊠ãã ããã
CXX
C++ ãšã®çžäºéçš ã»ã¯ã·ã§ã³ã§ã¯ã CXX ã®ç»åã䜿çšããŠããŸããã©ã€ã»ã³ã¹æ¡ä»¶ãå«ã詳 现ã«ã€ããŠã¯ãthird_party/cxx/ ãã£ã¬ã¯ã㪠ãåç
§ããŠãã ããã