I am trying to implement a simple program that stores a short sequence (let sample: Vec<u32>
) in the main vector (let mut samplesTable: Vec<Vec<u32>>
)
and has search index that maps that sequences to their corresponding index in the main vector.
A sequences represent statistic samples for some experiment. I need to be able to find the ID (the index in the samplesTable
) of a sample by its content.
Memory requirements will be high so the architecture of program better avoid redundancy.
So the search index is just a HashMap<&[u32], u32>
, where the first parameter is the full slice of sample from samplesTable
, and the second is the corresponding index of that sample.
The multithreaded version will be the next step.
This pattern is very important to me so I must to find a way to implement it in Rust.
What I've tried so far:
- Wrap all call sites of
addSample
in "{}" to create another scope. - Switched to nightly and forced
#![feature(nll)]
I'm using Windows 7 with Rust versions 1.35 and 1.36.
I'm using no external crates, it's a plain "cargo new --bin".
use std::collections::HashMap;
// Adds new sample to the table with the given index and updates index map.
// If there is an old sample, we insert the new sample with the 'id' from the old one.
// In this case 'id; parameter is should be zero and ignored in the function.
fn addSample<'a, 'b: 'a>(
oldSample: Option<Vec<u32>>,
newSample: Vec<u32>,
id: u32,
samplesTable: &'b mut Vec<Vec<u32>>,
indexMap: &'a mut HashMap<&'a [u32], u32>,
) {
// We have the oldSample, then replace it with the new one
if let Some(oldSampleTmp) = oldSample {
let oldID = indexMap.remove(oldSampleTmp.as_slice());
if let Some(oldId) = oldID {
samplesTable[oldId as usize] = newSample;
let slice: &[u32] = samplesTable[oldId as usize].as_slice();
indexMap.insert(slice, oldId);
} else {
panic!(
"addSample: oldSampleTmp was not found!\n oldSampleTmp={:?}",
oldSampleTmp
)
};
}
// We don't have the oldSample, so just insert newSample with provided 'id'
else {
samplesTable[id as usize] = newSample;
let slice: &[u32] = samplesTable[id as usize].as_slice();
indexMap.insert(slice, id);
}
} // end of the "addSample" function
fn main() {
// init our tables
let mut indexMap: HashMap<&[u32], u32> = HashMap::new();
let mut samplesTable: Vec<Vec<u32>> = Vec::with_capacity(3);
// prepare the sample data
let sampleA: Vec<u32> = vec![1, 2, 3];
let sampleB: Vec<u32> = vec![4, 5, 6];
let sampleC: Vec<u32> = vec![7, 8, 9];
// trying to fill the tables
addSample(None, sampleA, 1, &mut samplesTable, &mut indexMap);
addSample(None, sampleB, 2, &mut samplesTable, &mut indexMap);
addSample(None, sampleC, 3, &mut samplesTable, &mut indexMap);
// debug print
println!("indexMap is {:?}", &indexMap);
println!("index is {:?}", indexMap.get(vec![1, 2, 3].as_slice()));
}
The problem is that Rust generates this error:
error[E0499]: cannot borrow
samplesTable
as mutable more than once at a time
As far as I understand all modifications are contained in the body of "addSample". So after first call there should be no problem with the others in the same scope.