315 private links
TL;DR yes.
- creates-mirror
- cargo doc
cargo add <crate> --offlinefrom the global cache registry
But after programming in Rust for 10 years, I think that your coding style has the biggest impact on how your Rust code will look and feel.
People often say Rust’s syntax is ugly, but I’d argue the syntax is the least interesting thing about Rust. The semantics (the bits and pieces the language provides to express your ideas and how those bits combine to build interesting things) are much more important.
Parsing a .env can be clunky in basic algorithm, but elegant in Rust.
Tips:
read_to_string()instead of using a path, opening a file, creating a vector, adding the content to the vector to make a string- Use type inference:
let mut cfg = HashMap::new() - Lean into the typesystem:
.lines()to split strings safely and iterates over the linessplit_once()to get each key-value pair for each lines
- leverage error handling: use an enum to list all possible errors with important values and
thiserrorcan handle the error message
fn parse_config_file(path: &str) -> Result<HashMap<String, String>, ParseError> {
let content = read_to_string(path)?;
let mut config = HashMap::new();
for line in content.lines() {
match KeyValue::try_from(line) {
Ok(kv) => { config.insert(kv.key, kv.value); },
Err(ParseError::InvalidLine(_)) => continue, // Skip invalid lines
Err(e) => return Err(e), // Fail on any other error
}
}
Ok(config)
}
and why this code structure offers more extensibility!
Rust’s beauty is in its semantics and the core mechanics it provides: ownership, borrowing, pattern matching, traits, and so on. If you merely look at its (admittedly foreign) syntax, you overlook the real elegance of the language.
If there is anything that makes Rust “ugly”, it isn’t its syntax but the fact that it doesn’t hide the complexity underneath. Rust values explicitness and you have to deal with the harsh reality that computing is messy. Turns out our assumptions about a program’s execution are often wrong and our mental models are flawed.
Fortunately, we can encapsulate a lot of the complexity behind ergonomic abstractions; it just takes some effort! So don’t worry: once you start to confront your bad habits and look around for better abstractions, Rust stops being ugly.
A simple strategy to build subproceses that does one thing and one thing well.
An stdx
The project support project target dir selections compared to cargo-clean-recursive.
A feedback with Claude Fable 5 and how engineering can change.
And here is the problem: the encryption performs 2 passes over the data: first to encrypt, then to compute the authentication tag.
As we've seen before, it's bad because you will pay huge penalties when loading / unloading your data to / from memory to / from SIMD registers multiple times, even if you AES-CTR and GHash implementation are optimized to the mooooon.
The crate emits warning at compile timr when unwrap_wip is used.
The TL;DR is that iroh is a library and an architectural pattern to establish peer-to-peer QUIC connections between machines, even if they are behind routers (NAT gateways). It's not a replacement for WireGuard, HTTPS or BitTorrent, instead, it's a building block that you can use to build applications on top of it, but you need to bring your own application protocol and business logic. It's just a very dumb, very reliable pipe between 2 machines anywhere in the world.
Instead of building over UDP, the project builds over QUIC (that is over UDP).
Concepts:
- Endpoint: base unit of iroh. Two endpoints can establish a connection.
- Address: instead of IP addresses, endpoints have addresses that are Ed25519 signing keys.
- Connection: a QUIC connection between 2 endpoints. The connection use QUIC multipath extension, so the connection can flow through multiple pyssical paths.
- Relays: help endpoints punch holes through NATs and relay traffic when it's not possible. They allow to be internet-reachable. The default is the public relays provided by the N0 company, but a relay can be hosted and use privately.
- Discovery / Lookup: through DNS and pkarr signed packets to map an Ed25519 key to IP addresses.
- Transport: over UDP and QUIC handles the reliability and encryption. The transport can be carried over Bluetooth, Tor, radio or serial.
- protocol: application level communication (advertised in TLS' ALPN field of QUIC). A few are provided by iroh's team such as Blobs, RPC, HTTP/3
A perfect timing because:
- there is a growing sentiment against big tech and the US era of cooperation's end. Thus some are turning to build open and decentralized solutions.
- the invasion of Ukraine and industrial advances in China have revealed to the world the incredible leverage offered by cheap drones and robots. There is an area of semi-autonomous machines that need to communicate over heterogenous physical networks (radio, satellite, Wifi, ...) which is completely different that the traditional everything-over-internet (IP) model.
Current limitations of Iroh:
- rebrand to "P2P made easy" instead of "IP addresses break, dial keys instead"
- less bloated public API
- easier integration with application-layer protocols (plug-and-play HTTP/3)
- advanced routing and relay-to-relay communication.
Distributing Rust crates via git URLs instead of crates.io
Ok
instead of letting the call stack implicitly control what happens next (as recursion does), store the pending work in an explicit data structure such as a stack, queue, or heap. This turns control flow into ordinary data that can be inspected, paused, modified, or resumed.
Explicit stacks makes interruptions, limits, cancellation or interleaving work easier to work with. It's more adaptable to real-world constraints and test.
A stack (LIFO) produces depth-first search behavior.
A queue (FIFO) produces breadth-first search behavior.
- giving every integer a shared helper method: define a trait with two required methods and one default method,
- Making class AnimatedServo still count as a Servo: require a trait in another trait
- adding a method to a type you don't own: implement a new trait for the primitive type
- giving a tiny Enum a full set of standard behaviors: the standard traits already exist and
derive - making a wrapper feel like the thing inside it: the wrapper can implement the thing and implement
DerefandDerefMut - adding union to any collection of range sets: mock a wrapper around a BTreeSet for example
- treating fifteen integer-link types the same way: to avoid writing the same method bodies 15 times, write a
macro_rules - Giving Only OutputArray<8> (8 bits) a Byte-Oriented Method: implement a general methods in the general impl block. It's named Constraint-Gated Methods.
- How would you make some methods available only when the method’s type parameter has the required capabilities? Use
serdeandpostcardwith aHashMapstanding in for flash memory.
News about Lychee and why recursive link checking is not trivial.
Challanges:
One is named "distributed termination detection": know when you're done. "The classic solutions (Dijkstra–Scholten, token passing) just don’t map well onto Tokio’s channel-based world.
Another is the cycle because it's a DAG.
Then there is backpressure with the checker and the sender to the channel. If that channel is full, the response handler blocks; if it blocks, no responses are consumed; if no responses are consumed, no request slots free up.
Deduplication Races can occurs because the links are checks aynchrono
Leaky abstraction because the recursion spreads everywhere: reponses need to carry discovered links, requests need a depth, the collector need to understand recursive inputs, stats and formatters need to handle duplicates.
There is hope though because there is progress!
None of those are lychee problems. They’re hard concurrent-systems problems. We just lacked the vocabulary to talk about them, and while I wasn’t looking, those primitives got built. Sometimes the most important code you write for a feature is the code that never mentions the feature at all. So no, I don’t think we failed. We made progress by stumbling into the right direction.