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

Possibility to be zero-cost on some platforms #20

Open
ickk opened this issue Sep 5, 2024 · 4 comments
Open

Possibility to be zero-cost on some platforms #20

ickk opened this issue Sep 5, 2024 · 4 comments

Comments

@ickk
Copy link

ickk commented Sep 5, 2024

It would be possible (maybe slightly cursed?) to implement NonMaxU32 (and larger) in terms of some stable standard library type that already has a niche at u32::MAX, removing the run-time costs.

There unfortunately are not a lot of these, but I found std::os::fd::BorrowedFd which is available in std on Unix platforms & WASI and has been stable since 1.63.0.

Proof of concept

@13ros27
Copy link

13ros27 commented Oct 8, 2024

I'm not sure what you mean by 'and larger' as to my knowledge you can't construct larger types out of the smaller niched types because you will end up with too many niches? However there are still a few platform specific types available, all in std since 1.63:

@ickk
Copy link
Author

ickk commented Oct 8, 2024

@13ros27

However there are still a few platform specific types available

You're correct, I think the reason I didn't initially consider these was because their width changes depending on the platform's usize, so in practice you'll miss out on NonMaxU32 (which is what I was interested in) - but if this hack was to be deemed "ethical" it's probably still worth implementing NonMaxUsize and potentially NonMaxU64/NonMaxU32 in terms of those types where appropriate

I'm not sure what you mean by 'and larger'

It is possible to make larger types by composing a smaller non-max with normal primitives; i.e.

#[repr(C, align(8))]
pub struct NonMaxU64 {
  hi: NonMaxU32,
  lo: u32,
}

but the order of the fields probably needs to change based on the target platform's endianness (can be done with a cfg).
Proof of concept

What would be really great is if we found a natural NonMaxU8-like type somewhere in core or std, since then we could use it to build everything, but I never found such a type

@13ros27
Copy link

13ros27 commented Oct 8, 2024

Unfortunately combining types like this doesn't work because it will then have u32::MAX niches, for example assert_eq!(Some(0xFF_FF_FF_FF), dbg!(NonMaxU64::new(0xFF_FF_FF_FF)).map(|nm| nm.get())); fails. This is clearer to see if we reorder the fields at which point all the niches stack up at the end and size_of::<Option<Option<NonMaxU64>>>() becomes 8 rather than 16.

As an aside we can make NonMaxU8 by making an enum with 255 variants, see #18

@ickk
Copy link
Author

ickk commented Oct 8, 2024

You're right, that's my mistake

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