Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Minimally necessary Rust unsigned integer types on fields of structs, conditioned on typenum::consts as generic type parameters #203

Open
jymchng opened this issue Feb 16, 2024 · 2 comments

Comments

@jymchng
Copy link

jymchng commented Feb 16, 2024

Context:

I am writing sosecrets-rs.

Let's imagine that I have the following struct:

struct RunTimeSecret<T, MEC: Unsigned + MinimallyRepresentableUInt> {
    inner_secret: T,
    exposure_count: <MEC as MinimallyRepresentableUInt>::Type, // resolve to be `u8`
}

let var = RunTimeSecret::<String, U1> {
    inner_secret: "MySecret".to_string(),
    exposure_count: 256, // it does not compile and it should not compile because `256` > `u8::MAX`.
};

The intent of RunTimeSecret is to 'panic' or return an error only if exposure_count is greater than MEC::USIZE.

Now, I can always make the field exposure_count to be of type usize but that will be a waste because if MEC = U69, then u8 would be all that's needed to represent exposure_count since it is never larger than 69.

Summary:

I am trying to use typenum type-level integers to conditionally type fields of structs.

Attempt:

I wrote the following:

use typenum::{U1, Unsigned};

trait MinimallyRepresentableUInt {
    type Type;
}

impl MinimallyRepresentableUInt for U1 {
    type Type = u8;
}

Sadly, this is definitely not going to scale for all U<*>, i.e. U69, U64905405, etc.

Of course,

trait GiveMeu8AsExample<const N: usize> {
    type Type;
}

impl<const N: usize> GiveMeu8AsExample<N> for () {
    type Type = u8;
}

impl<T: Unsigned> MinimallyRepresentableUInt for T {
    type Type = <() as GiveMeu8AsExample::<{ <T as Unsigned>::USIZE }>>::Type;
}

this doesn't work because const generics expressions are not on stable Rust.

Just curious if there is a way to implement such a trait to all U<*> even if it involves macros and what not.

Playground

@paholg
Copy link
Owner

paholg commented Feb 19, 2024

I would guess that you could implement MinimallyRepresentableUInt for all U* generically.

I don't really have time to do this right now, but if you look at the implementations of some of the more complex functionality of typenum (such as division or gcd), it may give you some ideas.

Basically, Rust's type system is turing complete, so you can do pretty much anything. But the only tools are essentially recursion and branching, so code gets messy fast.

@jymchng
Copy link
Author

jymchng commented Feb 19, 2024

I would guess that you could implement MinimallyRepresentableUInt for all U* generically.

I don't really have time to do this right now, but if you look at the implementations of some of the more complex functionality of typenum (such as division or gcd), it may give you some ideas.

Basically, Rust's type system is turing complete, so you can do pretty much anything. But the only tools are essentially recursion and branching, so code gets messy fast.

@paholg

Thank you for your response. It's cool now, I've gotten help from another genius (like yourself :) on the Rust forum.

https://users.rust-lang.org/t/making-a-type-level-type-function-with-typenum-crate/107008/4?

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

2 participants