num-traits icon indicating copy to clipboard operation
num-traits copied to clipboard

IDEA: A definition of `FromBytes`/`ToBytes` that uses an associated constant instead of an associated type

Open SuperSamus opened this issue 6 months ago • 2 comments

(Note: this idea is currently only appliable on nightly, as it requires generic_const_exprs.)

FromBytes and ToBytes are declared like this:

pub trait FromBytes {
    type Bytes: NumBytes + ?Sized;
    fn from_be_bytes(bytes: &Self::Bytes) -> Self;
    // ...
}

This gives very little information to the argument/return type. All the implementations of NumBytes in num-traits are in the form of [u8; _], yet users of the library can't properly make use of it.

What the issue proposes is that these traits are implemented like this:

pub trait FromBytes {
    const NUM_BYTES: usize;
    fn from_be_bytes(bytes: [u8; Self::NUM_BYTES]) -> Self;
    // ...
}

An example where the current definition is unwieldy is the following:

use num_traits::FromBytes;

fn first_number<T: FromBytes>(arr: &[u8]) -> T {
    let bytes = arr.first_chunk().unwrap();
    FromBytes::from_ne_bytes(bytes)
}

pub fn main() {
    let arr = [2, 1, 0, 3 /*... */ ];
    println!("{}", first_number::<u8>(&arr)); // 2
    println!("{}", first_number::<u16>(&arr)); // 513
}

Which with the current definition doesn't compile. Granted, there is a workaround, but it's pretty ugly: Rust Playground.

This would obviously be a breaking change if the current traits are changed. Maybe it would be possible to create new traits with this definition instead of replacing the existing ones? I suppose that this is somewhat related to #294.

SuperSamus avatar May 21 '25 22:05 SuperSamus

I think this issue is the one to keep an eye on for enabling this and similar patterns that use traits' associated constants as const generic parameters: https://github.com/rust-lang/rust-project-goals/issues/100

tarcieri avatar May 21 '25 22:05 tarcieri

Note that types like BigInt and BigUint cannot specify a fixed NUM_BYTES at all, and they currently implement these traits from [u8] and to Vec<u8>.

cuviper avatar May 22 '25 00:05 cuviper