11use std:: {
22 borrow:: Cow ,
33 cell:: RefCell ,
4- collections:: BTreeSet ,
54 hash:: { Hash , Hasher } ,
65 sync:: Arc ,
76} ;
@@ -38,7 +37,7 @@ use crate::{
3837/// ```
3938pub struct ReplaceSource < T > {
4039 inner : Arc < T > ,
41- replacements : BTreeSet < ( Replacement , u32 ) > ,
40+ replacements : Vec < Replacement > ,
4241}
4342
4443/// Enforce replacement order when two replacement start and end are both equal
@@ -60,14 +59,16 @@ struct Replacement {
6059 content : String ,
6160 name : Option < String > ,
6261 enforce : ReplacementEnforce ,
62+ index : u32 ,
6363}
6464
6565impl Ord for Replacement {
6666 fn cmp ( & self , other : & Self ) -> std:: cmp:: Ordering {
67- ( self . start , self . end , self . enforce ) . cmp ( & (
67+ ( self . start , self . end , self . enforce , self . index ) . cmp ( & (
6868 other. start ,
6969 other. end ,
7070 other. enforce ,
71+ other. index ,
7172 ) )
7273 }
7374}
@@ -78,30 +79,12 @@ impl PartialOrd for Replacement {
7879 }
7980}
8081
81- impl Replacement {
82- pub fn new (
83- start : u32 ,
84- end : u32 ,
85- content : String ,
86- name : Option < String > ,
87- enforce : ReplacementEnforce ,
88- ) -> Self {
89- Self {
90- start,
91- end,
92- content,
93- name,
94- enforce,
95- }
96- }
97- }
98-
9982impl < T > ReplaceSource < T > {
10083 /// Create a [ReplaceSource].
10184 pub fn new ( source : T ) -> Self {
10285 Self {
10386 inner : Arc :: new ( source) ,
104- replacements : BTreeSet :: new ( ) ,
87+ replacements : Vec :: new ( ) ,
10588 }
10689 }
10790
@@ -136,16 +119,13 @@ impl<T: Source> ReplaceSource<T> {
136119 content : & str ,
137120 name : Option < & str > ,
138121 ) {
139- self . replacements . insert ( (
140- Replacement :: new (
141- start,
142- end,
143- content. into ( ) ,
144- name. map ( |s| s. into ( ) ) ,
145- ReplacementEnforce :: Normal ,
146- ) ,
147- self . replacements . len ( ) as u32 ,
148- ) ) ;
122+ self . replace_with_enforce (
123+ start,
124+ end,
125+ content,
126+ name,
127+ ReplacementEnforce :: Normal ,
128+ ) ;
149129 }
150130
151131 /// Create a replacement with content at `[start, end)`, with ReplacementEnforce.
@@ -157,16 +137,32 @@ impl<T: Source> ReplaceSource<T> {
157137 name : Option < & str > ,
158138 enforce : ReplacementEnforce ,
159139 ) {
160- self . replacements . insert ( (
161- Replacement :: new (
162- start,
163- end,
164- content. into ( ) ,
165- name. map ( |s| s. into ( ) ) ,
166- enforce,
167- ) ,
168- self . replacements . len ( ) as u32 ,
169- ) ) ;
140+ let replacement = Replacement {
141+ start,
142+ end,
143+ content : content. into ( ) ,
144+ name : name. map ( |s| s. into ( ) ) ,
145+ enforce,
146+ index : self . replacements . len ( ) as u32 ,
147+ } ;
148+
149+ if let Some ( last) = self . replacements . last ( ) {
150+ let cmp = replacement. cmp ( last) ;
151+ if cmp == std:: cmp:: Ordering :: Greater || cmp == std:: cmp:: Ordering :: Equal
152+ {
153+ self . replacements . push ( replacement) ;
154+ } else {
155+ let insert_at = match self
156+ . replacements
157+ . binary_search_by ( |other| other. cmp ( & replacement) )
158+ {
159+ Ok ( insert_at) | Err ( insert_at) => insert_at,
160+ } ;
161+ self . replacements . insert ( insert_at, replacement) ;
162+ }
163+ } else {
164+ self . replacements . push ( replacement) ;
165+ }
170166 }
171167}
172168
@@ -182,12 +178,12 @@ impl<T: Source + Hash + PartialEq + Eq + 'static> Source for ReplaceSource<T> {
182178 let max_len = self
183179 . replacements
184180 . iter ( )
185- . map ( |( replacement, _ ) | replacement. content . len ( ) )
181+ . map ( |replacement| replacement. content . len ( ) )
186182 . sum :: < usize > ( )
187183 + inner_source_code. len ( ) ;
188184 let mut source_code = String :: with_capacity ( max_len) ;
189185 let mut inner_pos = 0 ;
190- for ( replacement, _ ) in self . replacements . iter ( ) {
186+ for replacement in self . replacements . iter ( ) {
191187 if inner_pos < replacement. start {
192188 let end_pos = ( replacement. start as usize ) . min ( inner_source_code. len ( ) ) ;
193189 source_code. push_str ( & inner_source_code[ inner_pos as usize ..end_pos] ) ;
@@ -217,7 +213,7 @@ impl<T: Source + Hash + PartialEq + Eq + 'static> Source for ReplaceSource<T> {
217213 }
218214 let mut source_code = Rope :: new ( ) ;
219215 let mut inner_pos = 0 ;
220- for ( replacement, _ ) in self . replacements . iter ( ) {
216+ for replacement in self . replacements . iter ( ) {
221217 if inner_pos < replacement. start {
222218 let end_pos = ( replacement. start as usize ) . min ( inner_source_code. len ( ) ) ;
223219 let slice = inner_source_code. byte_slice ( inner_pos as usize ..end_pos) ;
@@ -314,7 +310,7 @@ impl<T: Source> StreamChunks for ReplaceSource<T> {
314310 on_name : crate :: helpers:: OnName < ' _ , ' a > ,
315311 ) -> crate :: helpers:: GeneratedInfo {
316312 let on_name = RefCell :: new ( on_name) ;
317- let mut replacements = self . replacements . iter ( ) . map ( | ( r , _ ) | r ) ;
313+ let mut replacements = self . replacements . iter ( ) ;
318314 let mut pos: u32 = 0 ;
319315 let mut replacement_end: Option < u32 > = None ;
320316 let mut next_replacement = replacements. next ( ) ;
@@ -722,8 +718,8 @@ impl<T: Source> Clone for ReplaceSource<T> {
722718impl < T : Hash > Hash for ReplaceSource < T > {
723719 fn hash < H : Hasher > ( & self , state : & mut H ) {
724720 "ReplaceSource" . hash ( state) ;
725- for ( repl , _ ) in self . replacements . iter ( ) {
726- repl . hash ( state) ;
721+ for replacement in self . replacements . iter ( ) {
722+ replacement . hash ( state) ;
727723 }
728724 self . inner . hash ( state) ;
729725 }
@@ -1137,7 +1133,7 @@ return <div>{data.foo}</div>
11371133 assert_eq ! ( source. map( & MapOptions :: default ( ) ) , None ) ;
11381134 let mut hasher = twox_hash:: XxHash64 :: default ( ) ;
11391135 source. hash ( & mut hasher) ;
1140- assert_eq ! ( format!( "{:x}" , hasher. finish( ) ) , "5781cda25d360a42 " ) ;
1136+ assert_eq ! ( format!( "{:x}" , hasher. finish( ) ) , "aec81d0020320dd3 " ) ;
11411137 }
11421138
11431139 #[ test]
0 commit comments