Let’s imagine there’s input from some device, that produces only zeros and ones and it needed to be converted into actual integers, something like
In this article, I will show how Rust functions can be generalized using generics and which problem I faced.
Here’s my first and naive implementation:
No magic, doing bit shift, and then XORing result with each bit. If it is 1 it will be added to result, if it is zero, zero remains in the rightmost position.
But there’s room for improvement.
fold function is more idiomatic:
The last solution is quite good, but it only produces an output of type
u8. What if we want to have
i64. Rust has support of Generic Data Types for cases like that, let’s try!
We will need
From<bool> traits to define behavior inside convert function:
But this implementation gives this error during compilation:
Hm, this doesn’t seem right. According to trait declaration, it has
Output defined as Associated type:
Based on documentation
BitXor has an implementation for
bool, which doesn’t have implementation for output of
Associated type is syntactic sugar and thankfully, Rust allows putting constraints on generic function implementation:
It also has a couple of other fixes, but generally, this is a working solution for all integer types.
What if I want to add the following to my function:
- Check if the input vector is larger than the target integer
- Check if the vector has only ones and zeros
- Reduce memory footprint, by changing input vector always be u8, and the return type will be derived from caller definition.
The first thing we need to do, is to change output type from plain
Result<T, ConversionError> where
ConversionError is an enum, that holds all error types we have:
To check the size of a generic type we will use
std::mem::size_of like that:
Changing the input vector to always be
u8 as the smallest integer is a questionable change because it forces always explicitly declare a return type, but I believe it is a fair deal for reducing memory size.
This is how it should be called now:
Function signature will change mainly in
Checking that input has only zeros and ones is optional, but can be done with simple filtering and counting:
The final solution with all latest changes: