Release 0.3.0 #8

Merged
warrence merged 69 commits from release-0.3.0 into main 2026-10-15 10:06:13 +02:00
Showing only changes of commit dd0ae64984 - Show all commits
+140
View File
@@ -142,6 +142,7 @@ impl<E: Copy, T: Clone> IndexMut<E> for ElementMap<E, T> {
#[cfg(test)] #[cfg(test)]
mod tests { mod tests {
use super::*; use super::*;
use std::rc::Rc;
#[test] #[test]
fn initial_values_are_default() { fn initial_values_are_default() {
@@ -238,4 +239,143 @@ mod tests {
"slot added by grow should hold the mapped default" "slot added by grow should hold the mapped default"
); );
} }
#[test]
fn remap() {
let mut source = ElementMap::new('-', |e| e, 3);
source[0] = 'a';
source[1] = 'b';
source[2] = 'c';
let mut mapping = ElementMap::new(usize::MAX, |e| e, 3);
mapping[0] = 2;
mapping[1] = 0;
mapping[2] = 1;
let template = ElementMap::new((), |f| f, 3);
let result = source.remap(&mapping, &template);
assert_eq!(result[0], 'b', "unexpected value at slot 0");
assert_eq!(result[1], 'c', "unexpected value at slot 1");
assert_eq!(result[2], 'a', "unexpected value at slot 2");
assert_eq!(
result.default, '-',
"default should be taken from the source map"
);
}
#[test]
fn remap_skips_default() {
let mut source = ElementMap::new(0, |e| e, 3);
source[0] = 1;
source[1] = 2;
source[2] = 3;
// Slot 1 stays unmapped, which would be out of bounds for the template if it was used.
let mut mapping = ElementMap::new(usize::MAX, |e| e, 3);
mapping[0] = 1;
mapping[2] = 0;
let template = ElementMap::new((), |f| f, 2);
let result = source.remap(&mapping, &template);
assert_eq!(result[0], 3, "unexpected value at slot 0");
assert_eq!(result[1], 1, "unexpected value at slot 1");
}
#[test]
fn remap_unmapped_slots() {
let mut source = ElementMap::new(9, |e| e, 2);
source[0] = 1;
source[1] = 2;
let mut mapping = ElementMap::new(usize::MAX, |e| e, 2);
mapping[0] = 0;
mapping[1] = 2;
let template = ElementMap::new((), |f| f, 4);
let result = source.remap(&mapping, &template);
assert_eq!(
result.data,
vec![1, 9, 2, 9],
"should have the template's length, with unmapped slots holding the source's default"
);
}
#[test]
fn remap_index_function() {
let mut source = ElementMap::<usize, i32>::new(0, |e| e, 3);
source[0] = 10;
source[1] = 20;
source[2] = 30;
let mut mapping = ElementMap::<usize, u32>::new(u32::MAX, |e| e, 3);
mapping[0] = 0;
mapping[1] = 1;
mapping[2] = 2;
// Reverses the order of the slots.
let template = ElementMap::<u32, ()>::new((), |f| 2 - f as usize, 3);
let result = source.remap(&mapping, &template);
assert_eq!(
result.data,
vec![30, 20, 10],
"values should be written at the slots given by the template's index function"
);
assert_eq!(
(result.to_index)(0),
2,
"index function should be taken from the template"
);
}
#[test]
fn remap_shorter_source() {
let mut source = ElementMap::new(9, |e| e, 2);
source[0] = 5;
source[1] = 6;
let mut mapping = ElementMap::new(usize::MAX, |e| e, 4);
for i in 0..4 {
mapping[i] = i;
}
let template = ElementMap::new((), |f| f, 4);
let result = source.remap(&mapping, &template);
assert_eq!(result.data, vec![5, 6, 9, 9], "unexpected data");
}
#[test]
fn remap_longer_source() {
let mut source = ElementMap::new(0, |e| e, 4);
for i in 0..4 {
source[i] = i + 1;
}
let mut mapping = ElementMap::new(usize::MAX, |e| e, 2);
mapping[0] = 1;
mapping[1] = 0;
let template = ElementMap::new((), |f| f, 2);
let result = source.remap(&mapping, &template);
assert_eq!(result.data, vec![2, 1], "unexpected data");
}
#[test]
fn remap_empty() {
let source = ElementMap::new(0, |e| e, 0);
let mapping = ElementMap::new(usize::MAX, |e| e, 0);
let template = ElementMap::new((), |f| f, 0);
let result = source.remap(&mapping, &template);
assert_eq!(result.data, Vec::<i32>::new(), "should be empty");
}
#[test]
fn remap_clones_values() {
let value = Rc::new(1);
let mut source = ElementMap::new(Rc::new(0), |e| e, 1);
source[0] = Rc::clone(&value);
let mut mapping = ElementMap::new(usize::MAX, |e| e, 1);
mapping[0] = 0;
let template = ElementMap::new((), |f| f, 1);
let _result = source.remap(&mapping, &template);
// The local variable, the source slot and the result slot each hold one reference.
assert_eq!(
Rc::strong_count(&value),
3,
"result should hold its own clone of the value"
);
drop(source);
assert_eq!(
Rc::strong_count(&value),
2,
"result should keep the value alive on its own"
);
}
} }