From 816046b3c8e3430bda09cd0e24cd3c4e138b02d4 Mon Sep 17 00:00:00 2001 From: Peter Kehl Date: Sun, 18 Sep 2022 13:46:25 -0700 Subject: [PATCH] Favicons; Cleanup --- README.md | 102 +++++++++++++++++++++-------------- README_BUILDS_AND_TESTING.md | 12 ++++- README_MORE_RESOURCES.md | 14 +++-- favicon-16x16.png | Bin 0 -> 798 bytes favicon-32x32.png | Bin 0 -> 2177 bytes favicon.ico | Bin 0 -> 15406 bytes favicon.png | Bin 0 -> 3432 bytes 7 files changed, 82 insertions(+), 46 deletions(-) create mode 100644 favicon-16x16.png create mode 100644 favicon-32x32.png create mode 100644 favicon.ico create mode 100644 favicon.png diff --git a/README.md b/README.md index 4cec489..9282144 100644 --- a/README.md +++ b/README.md @@ -1,18 +1,20 @@ - -This is only a part of a presentation. See -[https://peter-kehl.github.io/embedded_low_level_rust](embedded_low_level_rust) -for the whole. +This is only a part of [a presentation](./).That also shows any source code referred to below. + --- -# Embedded & low level-friendly, _no_std_ Rust intro -When viewing this [published as -slides](https://peter-kehl.github.io/embedded_low_level_rust): - 1. These slides are _not_ for mobile devices/tiny screens. See an alternative -[continuous -view](https://github.com/peter-kehl/embedded_low_level_rust/blob/main/README.md) -instead. - 2. **Zoom in**/**out** (because the slides can't be scrolled down). Press +# Embedded & low level-friendly, _no_std_ Rust crates +Viewing this [published as +slides](https://peter-kehl.github.io/no_std_rust_lib_presentation)? + 1. These slides are _not_ for mobile devices/tiny screens. See a limited + [alternative + view](https://github.com/peter-kehl/no_std_rust_lib_presentation/blob/main/README.md) + instead. + 2. **Zoom in**/**out** because the slides can't be scrolled down! Press **`Ctrl -`** or **`Ctrl +`** (**`Command -`** or **`Command +`** on Mac), or **`Ctrl`** (**`Command`**) and roll the **mouse wheel**, until you see numbers shown down to 0 below. @@ -21,11 +23,11 @@ instead. 5. Press the bottom left button for a menu (with list of slides & themes). 6. Press letter **`o`** (lowercase), or **`ESC`** key, to show (or hide) an **overview** of the nearby slides. - 7. Press **`Ctrl Shift F`** (probably **Command Shift F** on Mac) to show (or - hide) a **search** input (at the top right). Type the text to search for and - **Enter**. Click anywhere on the slide before using the keys to navigate - again. Any matching text will stay highlighted, even as you navigate to - other slides. (It highlights any matches on the overview screen, too.) + 7. Press **`Ctrl Shift F`** to show (or hide) a **search** input (at the top + right). Type the text to search for and **Enter**. Click anywhere on the + slide before using the keys to navigate again. This search is **sticky**: + Any matching text will stay highlighted, even as you navigate to other + slides. (It highlights any matches on the overview screen, too.) ``` 5 4 @@ -37,17 +39,17 @@ instead. Note: The content from this line on until the next slide (after the next horizontal line `---` in source of this file -[`README.md`](https://github.com/peter-kehl/embedded_low_level_rust/blob/main/README.md?plain=1)) +[`README.md`](https://github.com/peter-kehl/no_std_rust_lib_presentation/blob/main/README.md?plain=1)) is a "presenter's note". When viewing this in a browser as slides [on GitHub -Pages](https://peter-kehl.github.io/embedded_low_level_rust) or +Pages](https://peter-kehl.github.io/no_std_rust_lib_presentation) or [locally](index.html) (not opened from a filesystem, but through a local web server), you can show these notes by pressing "S". (You may need to allow browser to open a new window). See [Reveal.js > speaker view](https://revealjs.com/speaker-view). If you're seeing this as a [continuous -document](https://github.com/peter-kehl/embedded_low_level_rust/blob/main/README.md) -(instead of [slides](https://peter-kehl.github.io/embedded_low_level_rust)]): +document](https://github.com/peter-kehl/no_std_rust_lib_presentation/blob/main/README.md) +(instead of [slides](https://peter-kehl.github.io/no_std_rust_lib_presentation)]): - You will not be able to see source code examples as a part of this document. Instead, follow links to the respective source code. Those links highlight respective line ranges (which is valid unless this presentation gets out of @@ -58,16 +60,18 @@ document](https://github.com/peter-kehl/embedded_low_level_rust/blob/main/README This presentation loads external files (example code sources that it highlights and injects in its contents). In order to show them: - 1. Access this from a webserver (GitHub Pages, or a custom/local webserver) - - but not from a local file opened directly in browser. See [Reveal.js > + 1. Access this from a webserver (GitHub Pages, or a custom/local webserver). + 2. But don't open it from a local file opened directly in browser. See [Reveal.js > Markdown > External - Markdown](https://revealjs.com/markdown/#external-markdown). You do _not_ - need `npm` - for example, you can run `python3 -m http.server` instead. But + Markdown](https://revealjs.com/markdown/#external-markdown). + 3. You do _not_ + need `npm` - for example, you can run `python3 -m http.server` instead. + 4. But you need to run the webserver for a directory at least one level above the clone of this project - so that the webserver serves the neighbor projects, too. - Beware that, as of August 2022, `python3 -m http.server` and/or Firefox + 5. Beware that, as of August 2022, `python3 -m http.server` and/or Firefox caused `README*.md` files to be cached for up to 24 hours. Even refreshing the page in Firefox didn't help. It required purging Firefox cache (about:preferences#privacy > "Cookies and Site Data" > "Clear Data" button > @@ -96,7 +100,7 @@ TODO LATER: Move to a separate (visible) slide: Written in [Markdown](https://revealjs.com/markdown), rendered by [Reveal.js](https://github.com/hakimel/reveal.js) (also [https://revealjs.com](revealjs.com)). See also this [presentation's -source](https://github.com/peter-kehl/embedded_low_level_rust/blob/main/README.md?plain=1). +source](https://github.com/peter-kehl/no_std_rust_lib_presentation/blob/main/README.md?plain=1). ## Rendered with: Reveal.js If you'd like to render this locally (for example, when editing `README.md`), @@ -120,7 +124,7 @@ limit](https://docs.github.com/en/pages/getting-started-with-github-pages/about- of 100GB per month. Even though I'm sure visitors of this presentation itself won't make it go over -the bandwidth limit, it might reach the limit if authors of other presentations +that bandwidth limit, it might reach the limit if authors of other presentations link to (my) clones of `Reveal.js` and `RevealJS-Embed-Code`. Hence, please don't link to my clones. Instead, get your own clones of [Reveal.js](https://github.com/hakimel/reveal.js) and @@ -128,9 +132,8 @@ don't link to my clones. Instead, get your own clones of will also boost their GitHub projects. And while you're at it, please star their GitHub repositories, too). - To make this GitHub repository show up [on GitHub -Pages](https://peter-kehl.github.io/embedded_low_level_rust), I configured my +Pages](https://peter-kehl.github.io/no_std_rust_lib_presentation), I configured my clone repository's Settings > Pages > Source > Branch: `main` (and `/(root)`). Reveal.js uses [highlight.js](https://highlightjs.org/usage). In addition to @@ -170,7 +173,7 @@ Reveal.js can Unfortunately, Reveal.js doesn't support vertical scrolling through the slides: https://github.com/hakimel/reveal.js/issues/118. - --- # Audience and purpose @@ -395,14 +398,29 @@ https://github.com/hakimel/reveal.js/issues/118. * [`alloc::collections::BTreeSet`](https://doc.rust-lang.org/nightly/alloc/collections/index.html#reexport.BTreeSet), [`alloc::collections::BTreeMap`](https://doc.rust-lang.org/nightly/alloc/collections/index.html#reexport.BTreeMap) if your items/keys implement - [`core::comp::Ord`](https://doc.rust-lang.org/nightly/core/cmp/trait.Ord.html) - * either way, no - [`std::collections::HashSet`](https://doc.rust-lang.org/nightly/std/collections/struct.HashSet.html), - nor - [`std::collections::HashMap`](https://doc.rust-lang.org/nightly/std/collections/struct.HashMap.html) - (since those need a source of entropy), nor - [`std::thread::Thread`](https://doc.rust-lang.org/nightly/std/thread/struct.Thread.html) - (and no multi-threading) + [`core::comp::Ord`](https://doc.rust-lang.org/nightly/core/cmp/trait.Ord.html). + + Even if our `struct` (or `enum`) instances can't be ordered in human + terms, or if the actual order doesn't matter for us, we could define some + (predictable) order and use `BTreeSet/BTreeMap` for most types. + * either way (heapless or with heap) + * no [`std::collections::HashSet`](https://doc.rust-lang.org/nightly/std/collections/struct.HashSet.html), + nor + [`std::collections::HashMap`](https://doc.rust-lang.org/nightly/std/collections/struct.HashMap.html) + (since computing hashes needs a source of entropy). + + Are you creating a library for both `std` and `no_std`, and you'd like to + use `HashSet/HashMap` on `std`? You could define a trait, and implement it + for `HashSet` (or `HashMap`) and for your `no_std`-compatible type. Then + makde your API use + * const generics (heapless `no_std`-compatible, and can be instantiated and + then returned from a function), or + * or `&dyn` _`trait`_ (heapless `no_std`-compatible, but can't be + instantiated and then returned from a function), or + * `Box<&dyn` _`trait>`_ (`no_std` with heap) + * no + [`std::thread::Thread`](https://doc.rust-lang.org/nightly/std/thread/struct.Thread.html) + (and no multi-threading) * Rust has `#![no_std]`, but it doesn't have `#![std]`. (Instead, availability of `std` library is implied if you don't have `#![no_std]`). Here we use `std` to refer to [`std`](https://doc.rust-lang.org/nightly/std/index.html) @@ -567,6 +585,10 @@ transforms and/or filters the source data. [RNA Transcription](https://exercism.org/tracks/rust/exercises/rna-transcription) +In addition to the text of the assignment, it helps to see the +[tests](https://github.com/peter-kehl/x-rust/blob/main/rust/rna-transcription-std/tests/rna-transcription.rs) +(or the same tests used for [`no_std` version](https://github.com/peter-kehl/x-rust/blob/main/rust/rna-transcription-no_std-no_heap/tests/rna-transcription.rs)) + https://github.com/peter-kehl/x-rust/blob/main/rust/rna-transcription-std/src/lib.rs -https://github.com/peter-kehl/x-rust/blob/main/rust/rna-transcription/src/lib.rs +https://github.com/peter-kehl/x-rust/blob/main/rust/rna-transcription-no_std-no_heap/src/lib.rs diff --git a/README_BUILDS_AND_TESTING.md b/README_BUILDS_AND_TESTING.md index 79f2e09..57093d7 100644 --- a/README_BUILDS_AND_TESTING.md +++ b/README_BUILDS_AND_TESTING.md @@ -1,11 +1,19 @@ - This is only a part of a presentation. See [https://peter-kehl.github.io/embedded_low_level_rust](embedded_low_level_rust) for the whole presentation. --- +# Unit tests +* Even if a library itself is `no_std`, its unit tests (ones in modules marked with + `#[cfg(test)]`) are in a separate crate (auto-generated by `cargo test`). Hence they can use + `alloc`, even full `std`. -# no_std-friendly builds and testing (on desktop) +--- +# no_std-friendly builds and integration tests + * on desktop * no simple way to run/debug `no_std` on desktop * workaround: separate build verification and testing * build for a `no_std` target (but can't test, not even build the tests) diff --git a/README_MORE_RESOURCES.md b/README_MORE_RESOURCES.md index 8015365..2e8e5cc 100644 --- a/README_MORE_RESOURCES.md +++ b/README_MORE_RESOURCES.md @@ -1,4 +1,6 @@ - This is only a part of a presentation. See [https://peter-kehl.github.io/embedded_low_level_rust](embedded_low_level_rust) @@ -6,14 +8,14 @@ for the whole presentation. --- # More resources - * We can also have per-platform `rustflags` in `.cargo/config.toml`. See + * Per-platform `rustflags` in `.cargo/config.toml`. See [Zero2Prod > Faster Linking] (https://www.lpalmieri.com/posts/2020-06-06-zero-to-production-1-setup-toolchain-ides-ci/#5-1-faster-linking). - * You may want to try [The Embedded Rust book > + * [Embedded Rust book > QEMU](https://doc.rust-lang.org/nightly/embedded-book/start/qemu.html). (It's not suitable for multithreaded applications, but we can't use threads in `no_std` anyway.) - * [Cargo > Build + * [Cargo Reference > Build scripts](https://doc.rust-lang.org/nightly/cargo/reference/build-scripts.html) * [Unsafe code guidelines](https://rust-lang.github.io/unsafe-code-guidelines/layout.html) @@ -127,7 +129,11 @@ index;"> AFTER + Note: TODO highlight selected lines with TODO put GitHub code line range link at a commit here - to make this accessible. + +[arrform](https://docs.rs/arrform/latest/arrform) is an heapless no_std alternative to format!(...). +New to Rust? Exclamation mark indicates a macro invocation. diff --git a/favicon-16x16.png b/favicon-16x16.png new file mode 100644 index 0000000000000000000000000000000000000000..39b7eed9f1adc0b3973d8d7fee783c68dc6fd7b8 GIT binary patch literal 798 zcmV+(1L6FMP)210I6)X9tnZhxy$^K_rB`o;*^oW%+#XW^sWK-rOXZt})<%fqiOVEzn7A{P z-XJJyVHKf*gaAu$p{Yb%WMIGnyy7iDfwt=X+iC&7~CziVqn~X%N>qgfyUDzD9TAfufvOq)+xwj z^sPJ#9-d1K2-JO=Lp_PBo;R1KqBz!wo}pP(eRb~+vE6Qk-zUOq5%7I^2X4QDvZIkS z13n<&6(zhISwonHp)gtx$BGLYofh_X+JTN^;^6gc&GL#9o7*Bh-W|k63rLTP0>|xI zE6Xw_7FMyaO#U172sUUDZ80PF<*=XTiHWvrwzLAP2`eT>7 z7oGUE_8Z07@$mUY2&Q24IXtkx9i3F$s=JUJTGw2f#+IDxkR%DCbjqtb<`kY|>T!i6 zEBeNg1ZE4R3&Hb4O)4nCOxQ8hF{%ur6?om*#;M1&07*qoM6N<$f^o%iEdT%j literal 0 HcmV?d00001 diff --git a/favicon-32x32.png b/favicon-32x32.png new file mode 100644 index 0000000000000000000000000000000000000000..61c5725a4c3a687f16af5386c2898ffc945c7992 GIT binary patch literal 2177 zcmV-{2!8j8P)3&275?7rtCty%4c;-1Z9;$&iVKYqPEkZ4gaiz<@h?8il5%bW0+nkg7l>kdiiO z%2vLPFg<#6k1k7SKV;dW6k3C+-v%XpSoi{cx5R^)-s{ZJaKi@a+ z-E+@!&pqc{1z$}HrzCHgrsMCsi6vw2KjL_XNZc~-%XrhK$b>tQfgfs#ZxKFXH_=K6 z&tt?EB5#bjm*We>yJN~$aa>Heh`q#qBKBp1?xcX8lh+b25gB8ac{%=mOqq>(1zEMl z85)06=SVW1#1J3Xj|qL2qlXYrjSw4%*NFJ7O5Ch~OqSm=={{noQKz_;S7yT(j-jc; z4>ge#D-slLd~B*)*)YFYTkoa)op|^3fGDAgQ1TgSOPp|74A_2dQ24}yONq}2F;2Er z+b$6(FYYH65q6@BkiD(0tISq@^S~rc$gT@M{QB?LFc6AiMU@Nd=M}+j5>_A(jbr11 zD|oNf2e;LLpMGN^9==Pw5B%h>m+}6&K@oU_kXR`c7UC0PpD0jAyhUVc94YOTiFTv1 zV?_lfyR1+Y1&L%5qZAY*Tvj7Y265O8ipCP~g;dz6l!MTbCrO@5z7UqZcOKUQs;sN6 zJ;pW6@q6;)F#lCAF3(h^d+a#T7r;5bK-S5_E%YzPfSiaHgwtckA(2@f)adZYED`{@s37N{ijp#M-!=2V55S& zmKI}rY3_B)B0RUx9q7aJZ|{QJ?Z)QKn^9k14-;M5u%rx&%2TO!oSM5v@VEShSo`zm z(cj;XdGqGM@Aspo(1ESXDquCHydZ|1Z12OvJ3A3%)w!;~8*?&IJEIgfi%FX(`F+{; zi&*s38qA$LSMxwiON++vi+P3k;p~ZN3jF1?7Y)6c*s$qWXl`!CmMvQli^af{j?d`b z409^S1jA7@ooL7E!^7zcyf({@dx~>VUgXidFcOI|Tb)8*I0>WCh)^hWUEunf0<5jh zPg9`&*fsp}Ko`swD^yk0gbU@`3^@GMG))1q{^AucPIdNU?eRdm0h;PQvo4oV54b&ko=RpSJN7q`k(h2{!ClSp^%nK&(G{x`P!} z#gA`Rz;00R#@tNk;xUxvyEQLJ+1h%_ix>8FGLPTr$Y$hPvGvgk;oaC~W4D-8jDpPx2&4SrO~ot`4xFFkp4_FalgRm5O-^b}cPI_f;>us1FB^K@oy)X%A)ZL!O79>#dIk}twNmtj#9umkVoFIKY)%JeHMGzJ@ua-> z+l@NM-pB7oS(aJTbTk-6II3!z_YaQpnGwyI6Wkf7;sT=3tt4_(3T&kTJp=4R`NCo{ zASc_QdD3Ds!eKLMo^2b7V8J_Q5Kt4NqQF^tw(1Xy%CNN3t*xu|PP9boK!UlwyKe}W zy8CHe5~UMexQjumqbF{r1m|C1khNd)(Mt*@7v`YA!;Xs2(ugSHxiN;F=LYc1Czqve zw930TiB(U3&7*9rErEdy;>NCiHnLQp(Bsw^+j@twlqw zFNmWTd$fIBHX|QpxtW?FUETqDPeEahOWQs%;>D&8y!nM!J~znP4-wnkR=w>*p4Uo7 zxa{Q>uMfS$Bgo5iVxlXXy}E)md)nB`4QUoiFv=(-i%J!g@uBi8{B~g(TkRyS`3AX$ zpKD~G$m7z2_uN1Tk2JP27sTbfep^MWSB`JXz5MY$f0WFp5}Rs^QSP#6t{?OV&^N@S5s9KFn8369hY*Sz(2+nkZ~dLI#I&y zP?lG^FsHzYsU91$*-op>?fpC*OBydpH!C-tGD3QLA-PkuvAcGCymB(!jCP~JfI+tR zXS_i)cl&um@`>9;7ZLt_;!{F9hT|m9Gl`8vEn(&9P)vFq^pXttC$YgAE{n7f-z4OQ zBP2JfL&P-p7Tju?%-G<3X=)fB!XwqJiIDr_=OSDfZ||2ycfC{aVmRZ0ZNT-ob( z;%CH%Sra literal 0 HcmV?d00001 diff --git a/favicon.ico b/favicon.ico new file mode 100644 index 0000000000000000000000000000000000000000..ee5df437778bb127e24dfed08adfc9f4534cec40 GIT binary patch literal 15406 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 literal 0 HcmV?d00001 diff --git a/favicon.png b/favicon.png new file mode 100644 index 0000000000000000000000000000000000000000..628d8d7c2dec23e6caa807974054eeb1a6360fd8 GIT binary patch literal 3432 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 KMNUMnLSTZ0@{860 literal 0 HcmV?d00001