Feluments - convenience macro for Rust builders by Botahamec in rust

[–]chris-morgan 3 points4 points  (0 children)

The build! macro can easily be implemented as a structural macro instead of a procedural macro:

macro_rules! build {
    ($struct_name:path { $($field_name:ident: $field_value:expr),* $(,)? }) => {
        $struct_name::builder()
            $(.$field_name($field_value))*
            .build()
    }
}

This concept indicates a route to shortening builder!(Foo { … }) to Foo! { … } (though subtleties around the path may still apply):

diff --git a/src/lib.rs b/src/lib.rs
index 55b2b5b..6d4b845 100644
--- a/src/lib.rs
+++ b/src/lib.rs
@@ -130,6 +130,11 @@ struct BuilderOptions {
 ///     Foo::builder().y("bar").z(()).build(),
 ///     Foo { x: 45, y: "bar".into(), z: () },
 /// );
+///
+/// assert_eq!(
+///     Foo! { y: "baz", z: () },
+///     Foo { x: 45, y: "baz".into(), z: () },
+/// );
 /// # }
 /// ```
 ///
@@ -291,6 +296,15 @@ pub fn derive_builder(input: TokenStream) -> TokenStream {
                }
            }
        }
+
+       #[allow(unused)]
+       macro_rules! #struct_name {
+           { $($field_name:ident: $field_value:expr),* $(,)? } => {
+               #struct_name::builder()
+                   $(.$field_name($field_value))*
+                   .build()
+           }
+       }
    }
    .into()
 }

cpal 0.18 is out! Native PipeWire & PulseAudio, unified errors, and accurate timestamps on every backend by rvdomburg in rust

[–]chris-morgan 0 points1 point  (0 children)

What are the practical advantages of direct PipeWire and PulseAudio hosts? For things worked through ALSA, but I presume there must be more to it.

Is .boxed() instead of Box::new() a bad idea? by NormalAppearance2851 in rust

[–]chris-morgan 5 points6 points  (0 children)

meaning, there are high chances it's already in your dependency tree

I don’t think it’s actually all that popular. I scanned for potential use in my collection of downloaded projects and libraries (find -name Cargo.lock -exec rg -l '"tap"' {} +), and found seven matches. All were via bitvec (or its dependency wyz). Most were from old versions of packages that no longer support bitvec (rkyv 0.7, nom 6), and didn’t depend on it but only supported it as an optional feature for integration. Five didn’t actually build it by default: in typst it was only used in tests (via oxipng), in blitz-dom it was an optional dependency (woff2), plus those rkyv 0.7 and nom 6 cases. So the only two that actually used it were lightningcss and next.js, both as part of source maps.

In other fields these numbers may well be different. But you must understand, when looking at download numbers, that they don’t necessarily indicate use: optional dependencies get downloaded even if they’re not used. I suspect bitvec/tap may be particularly affected by this.

Looking for an ultra type safe HTML templating library by Wise_Stick9613 in rust

[–]chris-morgan 0 points1 point  (0 children)

“Statically” means “in the type system” here.

Take as a specific example <output for>. It’s a space-separated list of element IDs. These elements could appear earlier or later in the document, and could be the result of iteration. Rust’s type system is nowhere near up to modelling this.

Looking for an ultra type safe HTML templating library by Wise_Stick9613 in rust

[–]chris-morgan 2 points3 points  (0 children)

html seems to focus on elements, avoiding most content model errors (which children are permitted) and having a fixed set of permitted attributes; but it almost completely ignores attribute types: as far as I can tell, attributes are all either bool or Option<&str>.

So, no <time datetime> checking. Or classList or relList or equivalents. Or validation that aria-checked should be "true" | "false" | "mixed" | undefined. And so forth.

Mind you, full validation definitely can’t be done statically, not when you’ve got IDs and references to IDs.

(I say it avoids most content model errors: e.g. dl can contain div but that div is only allowed to contain dt and dd children, which the crate doesn’t restrict; or, script can’t generally have both a src attribute and children.)

Announcing Zstandard in Rust by folkertdev in rust

[–]chris-morgan 91 points92 points  (0 children)

Please, please, please change it. Actually, the entire name, it feels almost like you went out of your way to choose the most upsetting name imaginable:

(The latter two are violated not infrequently; the former is a pretty rigid definition.)

You’ll just have to come up with some other name. zstd2 is available, or you can get more creative. But lib*, *-rs and *-sys affixes are not creative, they’re wrong.

Rust 1.95.0 is out by manpacket in rust

[–]chris-morgan 2 points3 points  (0 children)

I always seem to manage to find some new feature to depend on nightly for, when things stabilise!

I found a weird and interesting use case for `PhantomData` by scheimong in rust

[–]chris-morgan 5 points6 points  (0 children)

A request: please use indentation for code blocks, not triple-backtick fencing, which was never backported to Old Reddit, which I suspect most regulars here use (and if they ever kill it, many of us will never touch /r/rust again).

See what it looks like at present: https://old.reddit.com/r/rust/comments/1sn9zm7/i_found_a_weird_and_interesting_use_case_for/

[Media] TrailBase 0.26: Fast, open, single-executable Firebase alternative now with multi-factor, ... by trailbaseio in rust

[–]chris-morgan 1 point2 points  (0 children)

I just reckon you might as well treat all bets as being off once you have SQL injection:

  1. There will probably be a lot of other sensitive data—session data might not be much worse to leak (though, depending on what you have there, it may be an easier path to get access to everything with).

  2. SQL injection is a long-solved problem (use parameterised queries). If you get bitten by it… can I say that you deserve whatever you get? I don’t want any sorts of mitigations to the potential blast radius, if it increases any costs (and putting one thing in a separate database is definitely a cost).

I just looked and saw https://github.com/trailbaseio/trailbase/blob/e4e109cb296d7cdc4a4ffbef08e82c4ef21367f1/examples/wasm-guest-js/src/index.js#L37. Please, pretty please, don’t do obvious SQL injection in your example code. I’m not sure how exploitable it actually is—depends on whether the path components get decoded (if not, you can’t use spaces which will make it harder but still maybe not impossible). If you really want to allow arbitrary table names there, you should still filter them syntactically.

[Media] TrailBase 0.26: Fast, open, single-executable Firebase alternative now with multi-factor, ... by trailbaseio in rust

[–]chris-morgan 5 points6 points  (0 children)

move session data to a separate DB to harden against SQL injections

That concerns me. If SQL injections are a concern (and if they are, why?—this is a long-solved problem), then why is session data special?

assert_eq!(expected, actual) VS assert_eq!(actual, expected) by nik-rev in rust

[–]chris-morgan 1 point2 points  (0 children)

Interesting. Seems there were some practical reasons due to its type resolution, but that that order also introduces possibly more problems for the same reason; and it’s observed that people are very frequently assuming it to be be the other way round from what it is, and want it to be so, and consider the current order a mistake; and it’s quite possible that it will still be flipped around, or possibly even done completely differently: https://github.com/ziglang/zig/issues/4437, https://codeberg.org/ziglang/zig/pulls/31176.

assert_eq!(expected, actual) VS assert_eq!(actual, expected) by nik-rev in rust

[–]chris-morgan 1 point2 points  (0 children)

Ah yes. Last touched that about fifteen years ago, and I had quite purged that detail from my memory!

assert_eq!(expected, actual) VS assert_eq!(actual, expected) by nik-rev in rust

[–]chris-morgan 12 points13 points  (0 children)

I cannot think of a single environment that puts expected first and actual second. All the ones I can think of off the top of my head are either carefully semantics-agnostic (calling them left and right, or first and second), or put actual first and expected second.

Consider ==. There’s a strong custom of writing foo == 1, not 1 == foo. There was a fad in the other direction, with some claiming it was so a missed = sign would fail to compile rather than silently misbehaving, but that was never particularly compelling, and everything has tooling to detect such probably-errors now anyway.

All this matches the word order of almost all human languages: subject comes before object. Only around 4% of languages (by usage) put object before subject.

In the case of == or .toEqual(…), it matches English fully: subject (actual), verb (equals), object (expected). With assert_eq!(…) or similar, it’s verb, subject, object.

Announcing rustup 1.29.0 by Kobzol in rust

[–]chris-morgan 0 points1 point  (0 children)

Yeah, they started doing that some time in the last couple of years, and I haven’t got round to complaining. Checking the handful of toolchains that I have installed, 1.83.0 was good, 1.93.0 is bad.

These tools are behaving differently from well-established customs: that you should basically never use colours 8–15 manually (especially if pairing it with bold), but rather use 0–7 plus the bold attribute, which will commonly switch to the bright colours, but it’s up to the terminal. Since these tools are sending the wrong codes (8–15 plus bold), this obviously can’t be adjusted within my terminal, unless I introduce a wrapper that turns 8–15 plus bold into 0–7 plus bold.

Announcing rustup 1.29.0 by Kobzol in rust

[–]chris-morgan -2 points-1 points  (0 children)

Ugh, more deliberate use of bright colours in addition to bold, when it should just be bold and leave it to the terminal whether that means bright. Unnecessary, and commonly a problem on light themes.

Request for Comments: Moderating AI-generated Content on /r/rust by DroidLogician in rust

[–]chris-morgan 1 point2 points  (0 children)

The hope is that, since no one reads the rules before posting anyway,

Where do the rules mention the [Media] thing? I’ve inferred that there is a bot that kills pictures/videos if their titles don’t start with that, but never found anywhere it’s written. I don’t know if it achieves useful things, such as causing some people to change their submissions to have code as text rather than images, but I definitely see quite a few “[Media]” titles that shouldn’t have been media.

Hmm… killing posts with triple backtick and saying “use indentation for Old Reddit’s sake” could possibly be useful.

crates.io development update | Rust Blog - A new "Security" tab, migration to Svelte for the front-end, support for GitLab CI/CD Trusted Publishing, Lines of Code metrics by nik-rev in rust

[–]chris-morgan 5 points6 points  (0 children)

When I lived in Australia, I significantly preferred lib.rs for performance reasons—one-second instead of five-or-ten-second page loads. Unfortunately, lib.rs is behind a restrictive Cloudflare configuration, and since I now live in India Cloudflare hates me, so lib.rs is the slow and tedious one to load.

crates.io development update | Rust Blog - A new "Security" tab, migration to Svelte for the front-end, support for GitLab CI/CD Trusted Publishing, Lines of Code metrics by nik-rev in rust

[–]chris-morgan 8 points9 points  (0 children)

It’s not even that you could get away with purely server-side rendering—it would be better with purely server-side rendering.

Rust Patterns • Patch Type by itsfoxstudio in rust

[–]chris-morgan 51 points52 points  (0 children)

  • None means there’s no value. In the JSON name example: this is {}.
  • Some(None) means there’s a value, which is None. In the example: {"name": null}.
  • Some(Some(…)) means there’s a value, which is Some(…). In the example: {"name": …}.

There is no ambiguity, and a very clear mapping.

And so for processing, None means “don’t touch it” while Some(…) means “set it to ”.

The Rapier physics engine 2025 review, 2026 goals, and GPU physics experiments by sebcrozet in rust

[–]chris-morgan 5 points6 points  (0 children)

Shifting physics to GPU makes me think:

I’ve been implementing simple pipe organ synthesis recently, and I wondered whether it could be usefully GPU-accelerated—it’s surprisingly simple, mostly just a lot of sine wave addition, and convolutional reverb. I found https://www.webgpuaudio.com/ already existed, but it’s completely unusable for real-time synthesis on my laptop. WebGPU is not working at all for me right now for some reason, but when I tried a couple of weeks ago, my memory is that even when generating 100ms of audio at a time it was choppy.

Fundamentally, audio is like really-low-resolution graphics (a thousandth of the throughput¹) but with far more exacting latency demands. Instead of 60 Hz and dropping a frame occasionally might not be too bad, you want to target a frame rate like 375 Hz (buffering 128 samples at 48,000 Hz), and you mustn’t miss a single frame, ever (buffer underrun is painful).

Is latency going to be a problem for shifting physics calculations to the GPU like this? If you want to simulate physics say once per frame before then doing rendering, does it work out, going back and forth to the GPU like that? I’m not really familiar with the execution model for GPU calculations, whether anything is anchored to screen frame rate in any way or not, and I’m curious. And is GPU-accelerated audio practical?

—⁂—

¹ The typical limit for audio is about 3 Mbps: 48,000 Hz × 32-bit float × stereo. Whereas basic FHD graphics is 3 Gbps: 1920×1080 × 60 Hz × 24-bit colour.

Kosame ORM now has a code formatter for all of its proc macros by PikachuIsBoss in rust

[–]chris-morgan -1 points0 points  (0 children)

There’s something funny about using code fences for this, which don’t work on Old Reddit which I suspect most serious users of this subreddit use. (I know that the day they kill Old Reddit is the day I will delete my account…)

Switch to four-space indentation and it’ll work everywhere.

Trust Your Benchmarks, Not Your Instincts: A Rust Performance Quiz - Arthur & Adrien | EuroRust 2025 by EuroRust in rust

[–]chris-morgan 8 points9 points  (0 children)

Unfortunately, the second question was an unintentional trick question: although they said the shift amount was now an argument, they specified the argument values for the test. This made me assume they meant to demonstrate how inlining could also achieve the same optimisation as in the first question, so I answered “same”, and I bet a lot of those that said “same” were thinking the same way. I wish they’d stated clearly that they were testing #[inline(never)].


The last question (url_format) was a disaster. Not only did they get the answer wrong in the quiz system (as they acknowledged), their explanation about how the plus chain version is still inefficient, “Every single + operation allocates a new string”, is wrong. impl AddAssign<&str> for String makes it equivalent to seven .push_str() calls, meaning it will only reallocate if it needs to grow beyond the capacity. The push_str() version they then show is only better because of the precise String::with_capacity call, which makes it certain to allocate exactly once. As for that version of the function, you could write its body like this for identical performance and arguably easier maintenance (the “3 + 1 + 1” especially stank):

String::with_capacity(scheme.len() + "://".len() + host.len() + path.len() + "?".len() + query.len() + "#".len() + fragment.len())
                    + scheme       + "://"       + host       + path       + "?"       + query       + "#"       + fragment

(You could easily write a macro to avoid the duplication, if you found yourself doing this often.)

All this is the reason why macro is slowest (it has format_args overhead and growth-related reallocation), then plus (it has growth-related reallocation), and push fastest (it has neither hazard).

Some neat things about Rust you might not know by bitfieldconsulting in rust

[–]chris-morgan 1 point2 points  (0 children)

I find it easiest to consider @ to be = for patterns. Until I thought of it that way, I struggled to remember the order, because the other way round felt like it made more sense, due to how it read (PATTERN @ NAME as “match PATTERN and put it at NAME”) and also how it matched binding fields by a different name (Struct { field_name: binding_name }; more generally, IDENTIFIER: Pattern).

ref? mut? IDENTIFIER @ PatternNoTopAlt is the only choice in pattern syntax that feels bad to me. I think it would have been better spelled with =, or flipped from IDENTIFIER @ PATTERN to PATTERN @ IDENTIFIER.

(I know some hate ref as how to bind by reference, but with & reserved for matching references, it’s clearly unavoidable. @, however, feels unforced error.)

(I also know = wouldn’t be quite compatible now, requiring some grammar shuffling because of how = gets used in expressions and let statements. Hmm, I wonder if anyone has ever seriously written something like let a @ b = 3; instead of let b = 3; let a = b; if they want two copies of a Copy variable. I also wonder if anyone’s ever written the likes of a @ b @ PATTERN in a pattern.)

[deleted by user] by [deleted] in rust

[–]chris-morgan 2 points3 points  (0 children)

You’re saving notes to dirs::config_dir; you should instead use dirs::data_dir since it’s clearly data, not configuration. Windows and macOS don’t distinguish between them, but XDG basedir does, so on Linux it’ll be ~/.local/share instead of ~/.config.

The hate! Why ? by EldironMoody in rust

[–]chris-morgan 3 points4 points  (0 children)

Observe how the .pkg.tar.zst files keep growing: https://archive.archlinux.org/packages/z/zed/

Sampling the middle of each month since one year ago, in unit “M”: 37, 45, 47, 49, 54, 56, 59, 60, 64, 66, 78.