smol-rust
Installation
SKILL.md
smol
smol is a small, fast, modular async runtime for Rust. The smol crate is a thin facade that re-exports a family of independent [smol-rs] crates (async-executor, async-io, async-channel, async-lock, async-net, async-fs, async-process, blocking, futures-lite). The reactor (async-io, built on polling) wraps epoll / kqueue / event ports / IOCP. Apply these conventions when building async Rust on smol. Current: smol 2.0.2, dual MIT/Apache-2.0. Upstream README/Cargo.toml now set MSRV to Rust 1.85 (crates.io metadata for the already-published 2.0.2 still reports 1.63), so target Rust 1.85+.
Core API (what smol:: gives you)
smol::block_on(future)— run a future to completion on the current thread. The entry point forfn mainand tests (smol has no required#[main]macro).smol::spawn(future) -> Task<T>— spawn onto smol's built-in global executor. Worker-thread count comes from theSMOL_THREADSenv var (default 1). You still need ablock_onsomewhere to drive progress on the calling thread.Task<T>— a spawned task handle. Dropping aTaskcancels it..awaitit for the result, or call.detach()to let it run independently. Forgetting this silently cancels work; if the program exits while global tasks are still running, their futures are abandoned and destructors may not run.Executor/LocalExecutor— composable executors when you don't want the global one.ex.spawn(fut),ex.spawn_many(...)for large batches, drive withblock_on(ex.run(future)).LocalExecutorruns!Sendfutures on one thread. See thesmol-macroscrate for declarativemain!/test!macros and multi-threadedExecutorsetup without proc-macro dependencies.Timer(async-io) —Timer::after(Duration),Timer::at(Instant),Timer::interval(Duration),Timer::interval_at(Instant, Duration),Timer::never(), plusset_after/set_at/set_interval/set_interval_atreset methods andwill_fire()..awaita one-shot timer for anInstant; poll an interval timer as a stream. Precision is platform-limited (Windows is roughly 16 ms) and timers may sleep longer, never less.Async<T>— wrap a pollable OS I/O handle (networking types and OS FDs such asTcpStream,UnixStream, timerfd, inotify) to make it async via the reactor.Async::newputs the handle in non-blocking mode;Async::new_nonblockingassumes you already did.async-netprovides ready-madeTcpStream/TcpListener/UdpSocket/Unix types built on it. Regular files and stdio are not safe/pollable here — useasync-fs(orUnblock) for those, notAsync. For custom operations preferread_with/write_with;get_mutand*_with_mutare unsafe because the inner I/O source must not be dropped.unblock(closure)/Unblock<T>(blockingcrate) — run blocking or CPU-heavy work on a dedicated thread pool.Unblock::new(std::io::stdout())adapts blocking I/O (stdio,std::fs::File) into async;unblock(|| expensive())offloads a closure.- Re-exported modules:
smol::io,smol::future,smol::stream,smol::pin,smol::ready(fromfutures-lite);smol::channel(mpmc),smol::lock(Mutex/RwLock/Semaphore/Barrier/OnceCell),smol::net,smol::fs,smol::process(smol::processis omitted ontarget_os = "espidf"). use smol::prelude::*;— brings inFuture,Stream, and the extension traits (FutureExt,StreamExt,AsyncReadExt,AsyncWriteExt,AsyncBufReadExt,AsyncSeekExt) so.next(),.read_to_end(),.race(), etc. are in scope.
use smol::{io, net, prelude::*, Unblock};