Reputation: 65
I'm currently trying to implement base64 encoding/decoding in rust as part of a larger project and needed a data structure for mapping the base64 character set to ASCII and vice versa. I found a barebones implementation of a bidirectional HashMap
in this StackOverflow answer, but since I need the base64 map to be a global variable in order for both encode/decode functions to access it, I can't just add the character mappings one by one. So I added another function to the BidiMap
implementation that does it in one batch (other function implementations are the same as in the link above):
impl<A, B> BidiMap<A, B>
where
A: Eq + Hash,
B: Eq + Hash,
{
// ...
pub fn from_array_with_u8_indices(values: &[B]) -> BidiMap<u8, B>
where B: Copy,
{
if values.len() > u8::MAX as usize + 1 {
panic!("This function should only be called with an array whose indices fit into an u8.");
}
let mut map: BidiMap<u8, B> = BidiMap::new();
for i in 0..values.len() {
map.insert(i as u8, values[i]);
}
map
}
// ...
}
I then call this function in another file, base64.rs:
use crate::datastructures::bidi_map::BidiMap;
const base64_values: [u8; 65] = [
0x41, 0x42, 0x43, ... , 0x3D,
];
const base64_map: BidiMap<u8, u8> = BidiMap::from_array_with_u8_indices(&base64_values);
But when I try to compile this code, I get the error
error[E0282]: type annotations needed
--> src/encodings/base64.rs:10:37
|
10 | const base64_map: BidiMap<u8, u8> = BidiMap::from_array_with_u8_indices(&base64_values);
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ cannot infer type for type parameter `A`
Even though I specified the types for A
and B
with BidiMap<u8, u8>
. I am pretty new to programming in rust and with generics in general, so it could be that I'm missing something really obvious, but I can't figure out what the solution to this problem is. I've already tried to change the function signature and implementation to return Self
instead of BidiMap<u8, B>
, but then it complained about not being able to cast the array indices to a generic type A
when calling map.insert()
.
Upvotes: 3
Views: 2391
Reputation: 42899
Here is a minimal example to reproduce your issue.
As you noted, the return type for from_array_with_u8_indices
is indeed correctly inferred.
However, the concrete type for BidiMap::from_array_with_u8_indices
cannot be inferred because the method is implemented for BidiMap<A, B>
. The return type is not related to this type.
Two possible fixes:
let map = BidiMap::<u8, u8>::from_array_with_u8_indices(&base64_values);
impl<B> BidiMap<u8, B>
where
B: Eq + Hash,
{
pub fn from_array_with_u8_indices(values: &[B]) -> Self
where
B: Copy,
{
let mut map: BidiMap<u8, B> = BidiMap::new();
//...
map
}
}
in which case you don't need to specify the type at all:
let base64_map = BidiMap::from_array_with_u8_indices(&base64_values);
Example of working code in the playground
Upvotes: 4