I came up with a function that is supposed to take any signed or unsigned integer and map it to a u8
. Every negative value becomes 0 while every value above 255 should be 255. I know this is trivial, my goal is only to get an understanding on how generics work.
use std::convert::TryInto;
fn as_byte<T>(source: T) -> u8
where
T: TryInto<u8>,
T: PartialOrd<u8>,
{
if source < 0 {
return 0;
}
if source > 255 {
return 255;
}
source.try_into().unwrap_or(0)
}
I thought it would make sense to constrain my generic to whatever I actually want to do with source
, so I declared that I want to be able to compare it to an u8
and be able to do a conversion to u8
(which should not fail if I catch a value out of range before).
If I call as_byte(1234i32)
, it will fail since there is no implementation of PartialOrd<u8>
for i32
. Even if there were an implementation, this will fail due to source
being moved on the first comparison and then being used after move in the second check.
If I pass source
by reference like as_byte(&1234i32)
it gets even worse. Now the TryInto<u8>
trait is not implemented either, since there is no From<&i32>
for u8
.
I understand why these issues are raised, but I can not figure out how to resolve them. I tried to change the constraints to where &'a T
or changed the parameter to source: &T
, or both. That left me with similar issues where traits for reference types were not implemented. This leaves me feeling like I didn't understand the concept of the borrowing/references correctly in the first place.
Where is the error in my thought process?
If
PartialOrd<u8> for i32
existed, what should this method's declaration look like?Knowing that
PartialOrd<u8> for i32
does not exist, how else should I constrain the type parameter? Why do I get the error "the trait `Foo` is not implemented for `&mut T`" even though T implements the trait? is related and somewhat answers my question - but I can (and probably should) not implement traits for primitive/std types, can I?
num
crate/project – Svetlin Zarev