2

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:

  1. Wrap all call sites of addSample in "{}" to create another scope.
  2. 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.

0 Answers0