prepass: use hash set to avoid duplicate heading ids
linear lookup becomes problematic for large amount of headings with same title
This commit is contained in:
parent
6a94e694f9
commit
87d4f7c270
1 changed files with 9 additions and 2 deletions
11
src/lib.rs
11
src/lib.rs
|
@ -378,6 +378,7 @@ impl<'s> PrePass<'s> {
|
||||||
fn new(src: &'s str, mut tree: block::Tree) -> Self {
|
fn new(src: &'s str, mut tree: block::Tree) -> Self {
|
||||||
let mut link_definitions = std::collections::HashMap::new();
|
let mut link_definitions = std::collections::HashMap::new();
|
||||||
let mut headings: Vec<Heading> = Vec::new();
|
let mut headings: Vec<Heading> = Vec::new();
|
||||||
|
let mut used_ids: std::collections::HashSet<&str> = std::collections::HashSet::new();
|
||||||
|
|
||||||
let mut inlines = span::InlineSpans::new(src);
|
let mut inlines = span::InlineSpans::new(src);
|
||||||
|
|
||||||
|
@ -435,7 +436,7 @@ impl<'s> PrePass<'s> {
|
||||||
id_auto.drain(id_auto.trim_end_matches('-').len()..);
|
id_auto.drain(id_auto.trim_end_matches('-').len()..);
|
||||||
|
|
||||||
// ensure id unique
|
// ensure id unique
|
||||||
if headings.iter().any(|h| h.id_auto == id_auto) || id_auto.is_empty() {
|
if used_ids.contains::<str>(&id_auto) || id_auto.is_empty() {
|
||||||
if id_auto.is_empty() {
|
if id_auto.is_empty() {
|
||||||
id_auto.push('s');
|
id_auto.push('s');
|
||||||
}
|
}
|
||||||
|
@ -443,13 +444,19 @@ impl<'s> PrePass<'s> {
|
||||||
id_auto.push('-');
|
id_auto.push('-');
|
||||||
let i_num = id_auto.len();
|
let i_num = id_auto.len();
|
||||||
write!(id_auto, "{}", num).unwrap();
|
write!(id_auto, "{}", num).unwrap();
|
||||||
while headings.iter().any(|h| h.id_auto == id_auto) {
|
while used_ids.contains::<str>(&id_auto) {
|
||||||
num += 1;
|
num += 1;
|
||||||
id_auto.drain(i_num..);
|
id_auto.drain(i_num..);
|
||||||
write!(id_auto, "{}", num).unwrap();
|
write!(id_auto, "{}", num).unwrap();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// SAFETY: used_ids is dropped before the id_auto strings in headings. even if
|
||||||
|
// the strings move due to headings reallocating, the string data on the heap
|
||||||
|
// will not move
|
||||||
|
used_ids.insert(unsafe {
|
||||||
|
std::mem::transmute::<&str, &'static str>(id_auto.as_ref())
|
||||||
|
});
|
||||||
headings.push(Heading {
|
headings.push(Heading {
|
||||||
location: e.span.start(),
|
location: e.span.start(),
|
||||||
id_auto,
|
id_auto,
|
||||||
|
|
Loading…
Reference in a new issue