Suggest adding a `BoundedInteger` trait
TL;DR: It would be nice if the types created by bounded_integer! implemented a BoundedInteger trait to allow some generic reflection on the bounds.
Hi there! Some background: I'm working on a crate for serializing and deserializing values as sequential integers. The idea is to serialize by recursively serializing the value's fields and then doing some math to combine them into a unique index. (And similarly by reversed for deserialization.)
This of course requires providing some core supported types. I've already handled integers and NonZero, and I figured I should add bounded integers as well. I started writing my own, but then I found this project which looks much nicer than anything I was going to throw together! 😄
My crate has a trait called Indexed that does most of the work. I could provide implementations for BoundedU8 and friends, but unfortunately as it stands today, I don't think my crate could implement Indexed for bounded_integer! types. They're independent newtypes, and I would need to know the min and max repr values for my math.
I was thinking that some sort of BoundedInteger trait would let my crate provide blanket implementations for supported reprs. Maybe something like:
pub unsafe trait BoundedInteger: Into<Self::Repr> + TryFrom<Self::Repr> {
type Repr;
const MIN_VALUE: Repr;
const MAX_VALUE: Repr;
}
That should be sufficient for my crate's needs. (Though of course you might add other bits of the bounded_integer! interface as well.) I marked the trait as unsafe because the const values would need to be trustworthy to safely call, e.g., new_unchecked.
I did see that the num-traits02 feature implements num::Bounded, but unfortunately that wouldn't work for me. My crate would need to use the bounds in const contexts, and that trait only provides runtime methods. (And anyway, I'd rather not require downstream crates to pull in num for one trait!)
Thanks for reading all this. I hope it makes sense, and I hope it's agreeable. I'd be happy to help with the implementation! (I couldn't guarantee a timeline—my project is already a side project—but since I'm the one asking for the feature maybe that's ok. 😄)
If you enable the bytemuck1 feature flag, the bounded integers implement Contiguous, which seems to be exactly what you are describing. Does it meet your needs?
Thanks for the suggestion. I had a look at that flag and the Contiguous trait. I think that would cover what my package needs, but I haven't had a chance to try it yet. One pitfall I can imagine would be overlaps between Contiguous and standard library types I've already implemented like NonZero—I'm hoping to gate this with a feature. We'll see!
It's a little unfortunate that it will require an extra dependency to access information the bounded_integer! macro already knows. The same info is already stamped on each type it creates. It's not the end of the world by any means! But I wouldn't need any actual functionality from bytemuck—just a way to name something from bounded-integer.
I'm curious if you would be opposed to adding a trait (which I would definitely respect!), or if you just suggested bytemuck as an expedient existing solution.
I do kind of see how bytemuck could be seen as a sort of “neutral third party,” so that handling Contiguous would handle other lots of other contiguous types and potentially even other bonded number libraries, which is a win for flexibility. But at the same time, bytemuck isn't the only bit-manipulation library, so having a trait in this library and implementing Contiguous would cover both axes.
Anyway, sorry to talk your ear off, and I hope this doesn't come across as argumentative. Thanks again!
Hmm. After playing around a bit, it looks like there will be conflict. But unfortunately I think there would also be conflict with a trait like I suggested. I should have realized that a blanket implementation like this would run afoul of the orphan rule. 🙁
I'll have to rethink my approach. I have a vague idea that I could provide a proc macro attribute to stick on bounded_integer! that would capture the type name from the body. At any rate, I can at least handle the BoundedX generic types.
It's a little unfortunate that it will require an extra dependency to access information the
bounded_integer!macro already knows.
Yeah, I wouldn’t be super opposed to adding our own trait. Just want to make sure what exactly your needs are first. If this orphan rule thing means it wouldn’t be useful anyway, I’d at least wait until someone needs it (I mean, I’d probably still accept a PR though).
That's very fair. Sigh. It all made so much sense in my mind until I actually, y' know, tried it. 😄 (Maybe some day when they figure out impl specialization.)