In summary, I want to have a function that digests a CSV file and depending on the existing values, it should decide with on_conflict
if the current value or the new value should be used.
However, I get the following error when I try to implement the function:
error[E0597]: `original_contents` does not live long enough
--> src/utils/result_writer.rs:66:17
|
58 | fn get_updated_contents<'old, 'new, 'out>(
| ---- lifetime `'old` defined here
59 | original_contents: String,
| ----------------- binding `original_contents` declared here
...
66 | let lines = original_contents.lines().skip(1);
| ^^^^^^^^^^^^^^^^^ borrowed value does not live long enough
...
74 | temp_lines.push(on_conflict(&columns[descriptor_values.len()..columns.len()].to_vec(), &value_values).to_vec());
| ------------------------------------------------------------------------------------- argument requires that `original_contents` is borrowed for `'old`
...
88 | }
| - `original_contents` dropped here while still borrowed
fn get_updated_contents<'old, 'new, 'out>(
original_contents: String,
descriptor_values: Vec<&str>,
value_values: Vec<&str>,
on_conflict: fn(&'old Vec<&'old str>, &'new Vec<&'new str>) -> &'out Vec<&'out str>,
) -> Vec<String>
where 'old: 'out, 'new: 'out {
let lines = original_contents.lines().skip(1);
let temp_lines: Vec<Vec<&str>> = {
let mut temp_lines = Vec::new();
for line in lines {
let columns: Vec<&str> = line.split(",").collect();
if columns.starts_with(&descriptor_values) {
temp_lines.push(on_conflict(&columns[descriptor_values.len()..columns.len()].to_vec(), &value_values).to_vec());
} else {
temp_lines.push(columns);
}
}
temp_lines.sort_by(compare_lines);
temp_lines
};
temp_lines
.iter()
.map(|line| line.join(","))
.collect()
}
I fixed it by using Higher-Rank Trait Bounds.
fn get_updated_contents(
old_contents: &str,
descriptor_values: &[&str],
value_values: &[&str],
on_conflict: for<'a> fn(&'a [&'a str], &'a [&'a str]) -> &'a [&'a str],
) -> Vec<String> {
let old_lines: Vec<Vec<&str>> = old_contents
.lines()
.skip(1)
.map(|line| line.split(",").collect())
.collect();
let new_lines: Vec<Vec<&str>> = {
let mut temp_lines: Vec<Vec<&str>> = Vec::new();
let mut found = false;
for i in 0..old_lines.len() {
let columns = &old_lines[i];
if columns.starts_with(&descriptor_values) {
found = true;
let mut new_line: Vec<&str> = Vec::new();
for i in 0..descriptor_values.len() {
new_line.push(descriptor_values[i]);
}
let old_values: &[&str] = &columns[descriptor_values.len()..columns.len()];
let result = on_conflict(old_values, value_values);
for value in result {
new_line.push(&value);
}
temp_lines.push(new_line);
} else {
temp_lines.push(columns.clone());
}
}
if !found {
let mut new_line = Vec::new();
new_line.extend_from_slice(&descriptor_values);
new_line.extend_from_slice(&value_values);
temp_lines.push(new_line);
}
temp_lines.sort_by(compare_lines);
temp_lines
};
new_lines
.iter()
.map(|line| line.join(","))
.collect()
}