@@ -71,6 +71,40 @@ pub(crate) enum NodeType {
7171unsafe impl < T : Send > Send for Node < T > { }
7272unsafe impl < T : Sync > Sync for Node < T > { }
7373
74+ struct InsertState < ' node , T > {
75+ parent : & ' node mut Node < T > ,
76+ child : Option < usize > ,
77+ }
78+
79+ impl < ' node , T > InsertState < ' node , T > {
80+ fn node ( & mut self ) -> & mut Node < T > {
81+ match self . child {
82+ None => self . parent ,
83+ Some ( i) => & mut self . parent . children [ i] ,
84+ }
85+ }
86+
87+ fn parent ( & mut self ) -> Option < & mut Node < T > > {
88+ match self . child {
89+ None => None ,
90+ Some ( _) => Some ( self . parent ) ,
91+ }
92+ }
93+
94+ fn set_child ( self , i : usize ) -> InsertState < ' node , T > {
95+ match self . child {
96+ None => InsertState {
97+ parent : self . parent ,
98+ child : Some ( i) ,
99+ } ,
100+ Some ( prev) => InsertState {
101+ parent : & mut self . parent . children [ prev] ,
102+ child : Some ( i) ,
103+ } ,
104+ }
105+ }
106+ }
107+
74108impl < T > Node < T > {
75109 // Insert a route into the tree.
76110 pub fn insert ( & mut self , route : String , val : T ) -> Result < ( ) , InsertError > {
@@ -88,21 +122,27 @@ impl<T> Node<T> {
88122 return Ok ( ( ) ) ;
89123 }
90124
91- let mut node = self ;
125+ let mut state = InsertState {
126+ parent : self ,
127+ child : None ,
128+ } ;
129+
92130 ' walk: loop {
93131 // Find the common prefix between the route and the current node.
94- let len = min ( remaining. len ( ) , node. prefix . len ( ) ) ;
132+ let len = min ( remaining. len ( ) , state . node ( ) . prefix . len ( ) ) ;
95133 let common_prefix = ( 0 ..len)
96134 . find ( |& i| {
97- remaining[ i] != node. prefix [ i]
135+ remaining[ i] != state . node ( ) . prefix [ i]
98136 // Make sure not confuse the start of a wildcard with an escaped `{`.
99- || remaining. is_escaped ( i) != node. prefix . is_escaped ( i)
137+ || remaining. is_escaped ( i) != state . node ( ) . prefix . is_escaped ( i)
100138 } )
101139 . unwrap_or ( len) ;
102140
103141 // If this node has a longer prefix than we need, we have to fork and extract the
104142 // common prefix into a shared parent.
105- if node. prefix . len ( ) > common_prefix {
143+ if state. node ( ) . prefix . len ( ) > common_prefix {
144+ let node = state. node ( ) ;
145+
106146 // Move the non-matching suffix into a child node.
107147 let suffix = node. prefix . as_ref ( ) . slice_off ( common_prefix) . to_owned ( ) ;
108148 let child = Node {
@@ -125,6 +165,8 @@ impl<T> Node<T> {
125165 }
126166
127167 if remaining. len ( ) == common_prefix {
168+ let node = state. node ( ) ;
169+
128170 // This node must not already contain a value.
129171 if node. value . is_some ( ) {
130172 return Err ( InsertError :: conflict ( & route, remaining, node) ) ;
@@ -144,20 +186,40 @@ impl<T> Node<T> {
144186
145187 // For parameters with a suffix, we have to find the matching suffix or
146188 // create a new child node.
147- if matches ! ( node. node_type, NodeType :: Param { .. } ) {
189+ if matches ! ( state . node( ) . node_type, NodeType :: Param { .. } ) {
148190 let terminator = remaining
149191 . iter ( )
150192 . position ( |& b| b == b'/' )
193+ // Include the '/' in the suffix.
151194 . map ( |b| b + 1 )
152195 . unwrap_or ( remaining. len ( ) ) ;
153196
154197 let suffix = remaining. slice_until ( terminator) ;
155198
156- for ( i, child) in node. children . iter ( ) . enumerate ( ) {
199+ if !matches ! ( * suffix, b"" | b"/" ) {
200+ if let Some ( parent) = state. parent ( ) {
201+ for child in & parent. children {
202+ // If there is a static prefix that also leads to this route
203+ // parameter, we have a prefix-suffix conflict.
204+ //
205+ // For example, `/prefix{a}` and `/{a}suffix` are conflicting, as there is no clear
206+ // choice to match against `/prefixsuffix`.
207+ if matches ! ( child. node_type, NodeType :: Static ) && child. wild_child {
208+ return Err ( InsertError :: conflict (
209+ & route,
210+ UnescapedRoute :: default ( ) . as_ref ( ) , // TODO
211+ child,
212+ ) ) ;
213+ }
214+ }
215+ }
216+ }
217+
218+ for ( i, child) in state. node ( ) . children . iter ( ) . enumerate ( ) {
157219 // Find a matching suffix.
158220 if * child. prefix == * * suffix {
159- node = & mut node . children [ i ] ;
160- node . priority += 1 ;
221+ state . node ( ) . priority += 1 ;
222+ state = state . set_child ( i ) ;
161223 continue ' walk;
162224 }
163225 }
@@ -168,19 +230,19 @@ impl<T> Node<T> {
168230 }
169231
170232 // If there is no matching suffix, create a new suffix node.
171- let child = node. add_suffix_child ( Node {
233+ let child = state . node ( ) . add_suffix_child ( Node {
172234 prefix : suffix. to_owned ( ) ,
173235 node_type : NodeType :: Static ,
174236 priority : 1 ,
175237 ..Node :: default ( )
176238 } ) ;
177- node. node_type = NodeType :: Param { suffix : true } ;
178- node = & mut node . children [ child] ;
239+ state . node ( ) . node_type = NodeType :: Param { suffix : true } ;
240+ state = state . set_child ( child) ;
179241
180242 // If this is the final route segment, insert the value.
181243 if terminator == remaining. len ( ) {
182- node. value = Some ( UnsafeCell :: new ( val) ) ;
183- node. remapping = remapping;
244+ state . node ( ) . value = Some ( UnsafeCell :: new ( val) ) ;
245+ state . node ( ) . remapping = remapping;
184246 return Ok ( ( ) ) ;
185247 }
186248
@@ -190,40 +252,61 @@ impl<T> Node<T> {
190252
191253 // Create a static node unless we are inserting a parameter.
192254 if remaining[ 0 ] != b'{' || remaining. is_escaped ( 0 ) {
193- let child = node. add_child ( Node {
255+ let child = state . node ( ) . add_child ( Node {
194256 node_type : NodeType :: Static ,
195257 priority : 1 ,
196258 ..Node :: default ( )
197259 } ) ;
198- node. indices . push ( remaining[ 0 ] ) ;
199- node = & mut node . children [ child] ;
260+ state . node ( ) . indices . push ( remaining[ 0 ] ) ;
261+ state = state . set_child ( child) ;
200262 }
201263
202264 // Insert the remaining route.
203- let last = node. insert_route ( remaining, val) ?;
265+ let last = state . node ( ) . insert_route ( remaining, val) ?;
204266 last. remapping = remapping;
205267 return Ok ( ( ) ) ;
206268 }
207269
208270 // Find a child node that matches the next character in the route.
209- for mut i in 0 ..node. indices . len ( ) {
210- if next == node. indices [ i] {
271+ for mut i in 0 ..state . node ( ) . indices . len ( ) {
272+ if next == state . node ( ) . indices [ i] {
211273 // Make sure not confuse the start of a wildcard with an escaped `{` or `}`.
212274 if matches ! ( next, b'{' | b'}' ) && !remaining. is_escaped ( 0 ) {
213275 continue ;
214276 }
215277
216278 // Continue searching in the child.
217- i = node. update_child_priority ( i) ;
218- node = & mut node . children [ i ] ;
279+ i = state . node ( ) . update_child_priority ( i) ;
280+ state = state . set_child ( i ) ;
219281 continue ' walk;
220282 }
221283 }
222284
223285 // We couldn't find a matching child.
224286 //
225287 // If we're not inserting a wildcard we have to create a static child.
226- if ( next != b'{' || remaining. is_escaped ( 0 ) ) && node. node_type != NodeType :: CatchAll {
288+ if ( next != b'{' || remaining. is_escaped ( 0 ) )
289+ && state. node ( ) . node_type != NodeType :: CatchAll
290+ {
291+ let node = state. node ( ) ;
292+
293+ let terminator = remaining
294+ . iter ( )
295+ . position ( |& b| b == b'/' )
296+ . unwrap_or ( remaining. len ( ) ) ;
297+
298+ if let Ok ( Some ( wildcard) ) = find_wildcard ( remaining. slice_until ( terminator) ) {
299+ // If there is a parameter prefix and this node also has a parameter suffix, we
300+ // have a prefix-suffix conflict.
301+ if wildcard. start > 0 && node. wild_child {
302+ let wild_child = node. children . last ( ) . unwrap ( ) ;
303+
304+ if matches ! ( wild_child. node_type, NodeType :: Param { suffix: true } ) {
305+ return Err ( InsertError :: conflict ( & route, remaining, wild_child) ) ;
306+ }
307+ }
308+ }
309+
227310 node. indices . push ( next) ;
228311 let child = node. add_child ( Node :: default ( ) ) ;
229312 let child = node. update_child_priority ( child) ;
@@ -237,29 +320,30 @@ impl<T> Node<T> {
237320 // We're trying to insert a wildcard.
238321 //
239322 // If this node already has a wildcard child, we have to make sure it matches.
240- if node. wild_child {
323+ if state . node ( ) . wild_child {
241324 // Wildcards are always the last child.
242- node = node. children . last_mut ( ) . unwrap ( ) ;
243- node. priority += 1 ;
325+ let wild_child = state. node ( ) . children . len ( ) - 1 ;
326+ state = state. set_child ( wild_child) ;
327+ state. node ( ) . priority += 1 ;
244328
245329 // Make sure the route parameter matches.
246- if let Some ( wildcard) = remaining. get ( ..node. prefix . len ( ) ) {
247- if * wildcard != * node. prefix {
248- return Err ( InsertError :: conflict ( & route, remaining, node) ) ;
330+ if let Some ( wildcard) = remaining. get ( ..state . node ( ) . prefix . len ( ) ) {
331+ if * wildcard != * state . node ( ) . prefix {
332+ return Err ( InsertError :: conflict ( & route, remaining, state . node ( ) ) ) ;
249333 }
250334 }
251335
252336 // Catch-all routes cannot have children.
253- if node. node_type == NodeType :: CatchAll {
254- return Err ( InsertError :: conflict ( & route, remaining, node) ) ;
337+ if state . node ( ) . node_type == NodeType :: CatchAll {
338+ return Err ( InsertError :: conflict ( & route, remaining, state . node ( ) ) ) ;
255339 }
256340
257341 // Continue with the wildcard node.
258342 continue ' walk;
259343 }
260344
261345 // Otherwise, create a new node for the wildcard and insert the route.
262- let last = node. insert_route ( remaining, val) ?;
346+ let last = state . node ( ) . insert_route ( remaining, val) ?;
263347 last. remapping = remapping;
264348 return Ok ( ( ) ) ;
265349 }
0 commit comments