On Wed Feb 19, 2025 at 5:51 AM JST, Timur Tabi wrote:> On Tue, 2025-02-18 at 22:16 +0900, Alexandre Courbot wrote: >> > A proper struct with `high` and `low` might be more verbose, but >> > it rules out this issue. >> >> Mmm indeed, so we would have client code looking like: >> >> ? let SplitU64 { high, low } = some_u64.into_u32(); >> >> instead of >> >> ? let (high, low) = some_u64.into_u32(); >> >> which is correct, and >> >> ? let (low, high) = some_u64.into_u32(); >> >> which is incorrect, but is likely to not be caught. > > I'm new to Rust, so let me see if I get this right. > > struct SplitU64 { > high: u32, > low: u32 > } > > So if you want to extract the upper 32 bits of a u64, you have to do this: > > let split = some_u64.into_u32s(); > let some_u32 = split.high;More likely this would be something like: let SplitU64 { high: some_u32, .. } = some_u64; Which is still a bit verbose, but a single-liner. Actually. How about adding methods to this trait that return either component? let some_u32 = some_u64.high_half(); let another_u32 = some_u64.low_half(); These should be used most of the times, and using destructuring/tuple would only be useful for a few select cases.> > as opposed to your original design: > > let (some_u32, _) = some_u64.into_u32s(); > > Personally, I prefer the latter. The other advantage is that into_u32s and > from_u32s are reciprocal: > > assert_eq!(u64::from_u32s(u64::into_u32s(some_u64)), some_u64); > > (or something like that)Yeah, having symmetry is definitely nice. OTOH there are no safeguards against mixing up the order and the high and low components, so a compromise will have to be made one way or the other. But if we also add the methods I proposed above, that question should matter less.
On 2/18/25 5:21 PM, Alexandre Courbot wrote:> On Wed Feb 19, 2025 at 5:51 AM JST, Timur Tabi wrote: >> On Tue, 2025-02-18 at 22:16 +0900, Alexandre Courbot wrote:...> More likely this would be something like: > > let SplitU64 { high: some_u32, .. } = some_u64; > > Which is still a bit verbose, but a single-liner. > > Actually. How about adding methods to this trait that return either > component? > > let some_u32 = some_u64.high_half(); > let another_u32 = some_u64.low_half(); > > These should be used most of the times, and using destructuring/tuple > would only be useful for a few select cases.I think I like this approach best so far, because that is actually how drivers tend to use these values: one or the other 32 bits at a time. Registers are often grouped into 32-bit named registers, and driver code wants to refer to them one at a time (before breaking some of them down into smaller named fields)> The .high_half() and .low_half() approach matches that very closely. And it's simpler to read than the SplitU64 API, without losing anything we need, right? thanks, -- John Hubbard
Sergio González Collado
2025-Feb-19 20:12 UTC
[PATCH RFC 1/3] rust: add useful ops for u64
> Actually. How about adding methods to this trait that return either > component? > > let some_u32 = some_u64.high_half(); > let another_u32 = some_u64.low_half(); > > These should be used most of the times, and using destructuring/tuple > would only be useful for a few select cases. >Indeed very nice!