@@ -2,6 +2,8 @@ use std::fmt::{self, Debug, Formatter};
2
2
use std:: hash:: Hash ;
3
3
use std:: num:: NonZeroUsize ;
4
4
5
+ use indexmap:: IndexMap ;
6
+
5
7
use super :: { Content , Selector } ;
6
8
use crate :: diag:: StrResult ;
7
9
use crate :: doc:: { Frame , FrameItem , Meta , Position } ;
@@ -83,7 +85,7 @@ impl StabilityProvider {
83
85
/// Can be queried for elements and their positions.
84
86
pub struct Introspector {
85
87
pages : usize ,
86
- elems : Vec < ( Content , Position ) > ,
88
+ elems : IndexMap < Option < Location > , ( Content , Position ) > ,
87
89
// Indexed by page number.
88
90
page_numberings : Vec < Value > ,
89
91
}
@@ -93,7 +95,7 @@ impl Introspector {
93
95
pub fn new ( frames : & [ Frame ] ) -> Self {
94
96
let mut introspector = Self {
95
97
pages : frames. len ( ) ,
96
- elems : vec ! [ ] ,
98
+ elems : IndexMap :: new ( ) ,
97
99
page_numberings : vec ! [ ] ,
98
100
} ;
99
101
for ( i, frame) in frames. iter ( ) . enumerate ( ) {
@@ -105,7 +107,7 @@ impl Introspector {
105
107
106
108
/// Iterate over all elements.
107
109
pub fn all ( & self ) -> impl Iterator < Item = & Content > {
108
- self . elems . iter ( ) . map ( |( elem, _) | elem)
110
+ self . elems . values ( ) . map ( |( elem, _) | elem)
109
111
}
110
112
111
113
/// Extract metadata from a frame.
@@ -119,13 +121,14 @@ impl Introspector {
119
121
self . extract ( & group. frame , page, ts) ;
120
122
}
121
123
FrameItem :: Meta ( Meta :: Elem ( content) , _)
122
- if !self
123
- . elems
124
- . iter ( )
125
- . any ( |( prev, _) | prev. location ( ) == content. location ( ) ) =>
124
+ if !self . elems . contains_key ( & content. location ( ) ) =>
126
125
{
127
126
let pos = pos. transform ( ts) ;
128
- self . elems . push ( ( content. clone ( ) , Position { page, point : pos } ) ) ;
127
+ let ret = self . elems . insert (
128
+ content. location ( ) ,
129
+ ( content. clone ( ) , Position { page, point : pos } ) ,
130
+ ) ;
131
+ assert ! ( ret. is_none( ) , "duplicate locations" ) ;
129
132
}
130
133
FrameItem :: Meta ( Meta :: PageNumbering ( numbering) , _) => {
131
134
self . page_numberings . push ( numbering. clone ( ) ) ;
@@ -202,8 +205,7 @@ impl Introspector {
202
205
/// Find the position for the given location.
203
206
pub fn position ( & self , location : Location ) -> Position {
204
207
self . elems
205
- . iter ( )
206
- . find ( |( elem, _) | elem. location ( ) == Some ( location) )
208
+ . get ( & Some ( location) )
207
209
. map ( |( _, loc) | * loc)
208
210
. unwrap_or ( Position { page : NonZeroUsize :: ONE , point : Point :: zero ( ) } )
209
211
}
0 commit comments