@@ -352,105 +352,57 @@ impl Resource {
352
352
from : & mut Arc < Resource > ,
353
353
suffix : & str ,
354
354
) -> Arc < Resource > {
355
- if suffix . is_empty ( ) {
355
+ let Some ( ( chunk , rest ) ) = Self :: split_first_chunk ( suffix ) else {
356
356
Resource :: upgrade_resource ( from, tables. hat_code . new_resource ( ) ) ;
357
- from. clone ( )
358
- } else if let Some ( stripped_suffix) = suffix. strip_prefix ( '/' ) {
359
- let ( chunk, rest) = match stripped_suffix. find ( '/' ) {
360
- Some ( idx) => ( & suffix[ 0 ..( idx + 1 ) ] , & suffix[ ( idx + 1 ) ..] ) ,
361
- None => ( suffix, "" ) ,
362
- } ;
363
-
364
- match get_mut_unchecked ( from) . children . get_mut ( chunk) {
365
- Some ( res) => Resource :: make_resource ( tables, res, rest) ,
366
- None => {
367
- let mut new = Arc :: new ( Resource :: new ( from, chunk, None ) ) ;
368
- if tracing:: enabled!( tracing:: Level :: DEBUG ) && rest. is_empty ( ) {
369
- tracing:: debug!( "Register resource {}" , new. expr( ) ) ;
370
- }
371
- let res = Resource :: make_resource ( tables, & mut new, rest) ;
372
- get_mut_unchecked ( from)
373
- . children
374
- . insert ( String :: from ( chunk) , new) ;
375
- res
376
- }
377
- }
378
- } else {
379
- match from. parent . clone ( ) {
380
- Some ( mut parent) => {
381
- Resource :: make_resource ( tables, & mut parent, & [ & from. suffix , suffix] . concat ( ) )
382
- }
383
- None => {
384
- let ( chunk, rest) = match suffix[ 1 ..] . find ( '/' ) {
385
- Some ( idx) => ( & suffix[ 0 ..( idx + 1 ) ] , & suffix[ ( idx + 1 ) ..] ) ,
386
- None => ( suffix, "" ) ,
387
- } ;
388
-
389
- match get_mut_unchecked ( from) . children . get_mut ( chunk) {
390
- Some ( res) => Resource :: make_resource ( tables, res, rest) ,
391
- None => {
392
- let mut new = Arc :: new ( Resource :: new ( from, chunk, None ) ) ;
393
- if tracing:: enabled!( tracing:: Level :: DEBUG ) && rest. is_empty ( ) {
394
- tracing:: debug!( "Register resource {}" , new. expr( ) ) ;
395
- }
396
- let res = Resource :: make_resource ( tables, & mut new, rest) ;
397
- get_mut_unchecked ( from)
398
- . children
399
- . insert ( String :: from ( chunk) , new) ;
400
- res
401
- }
402
- }
403
- }
357
+ return from. clone ( ) ;
358
+ } ;
359
+ if !chunk. starts_with ( '/' ) {
360
+ if let Some ( parent) = & mut from. parent . clone ( ) {
361
+ return Resource :: make_resource ( tables, parent, & [ & from. suffix , suffix] . concat ( ) ) ;
404
362
}
405
363
}
364
+ if let Some ( child) = get_mut_unchecked ( from) . children . get_mut ( chunk) {
365
+ return Resource :: make_resource ( tables, child, rest) ;
366
+ }
367
+ let mut new = Arc :: new ( Resource :: new ( from, chunk, None ) ) ;
368
+ if rest. is_empty ( ) {
369
+ tracing:: debug!( "Register resource {}" , new. expr( ) ) ;
370
+ }
371
+ let res = Resource :: make_resource ( tables, & mut new, rest) ;
372
+ get_mut_unchecked ( from)
373
+ . children
374
+ . insert ( String :: from ( chunk) , new) ;
375
+ res
406
376
}
407
377
408
378
#[ inline]
409
379
pub fn get_resource ( from : & Arc < Resource > , suffix : & str ) -> Option < Arc < Resource > > {
410
- if suffix. is_empty ( ) {
411
- Some ( from. clone ( ) )
412
- } else if let Some ( stripped_suffix) = suffix. strip_prefix ( '/' ) {
413
- let ( chunk, rest) = match stripped_suffix. find ( '/' ) {
414
- Some ( idx) => ( & suffix[ 0 ..( idx + 1 ) ] , & suffix[ ( idx + 1 ) ..] ) ,
415
- None => ( suffix, "" ) ,
416
- } ;
417
-
418
- match from. children . get ( chunk) {
419
- Some ( res) => Resource :: get_resource ( res, rest) ,
420
- None => None ,
421
- }
422
- } else {
423
- match & from. parent {
424
- Some ( parent) => Resource :: get_resource ( parent, & [ & from. suffix , suffix] . concat ( ) ) ,
425
- None => {
426
- let ( chunk, rest) = match suffix[ 1 ..] . find ( '/' ) {
427
- Some ( idx) => ( & suffix[ 0 ..( idx + 1 ) ] , & suffix[ ( idx + 1 ) ..] ) ,
428
- None => ( suffix, "" ) ,
429
- } ;
430
-
431
- match from. children . get ( chunk) {
432
- Some ( res) => Resource :: get_resource ( res, rest) ,
433
- None => None ,
434
- }
435
- }
380
+ let Some ( ( chunk, rest) ) = Self :: split_first_chunk ( suffix) else {
381
+ return Some ( from. clone ( ) ) ;
382
+ } ;
383
+ if !chunk. starts_with ( '/' ) {
384
+ if let Some ( parent) = & from. parent {
385
+ return Resource :: get_resource ( parent, & [ & from. suffix , suffix] . concat ( ) ) ;
436
386
}
437
387
}
388
+ Resource :: get_resource ( from. children . get ( chunk) ?, rest)
438
389
}
439
390
440
- fn fst_chunk ( key_expr : & keyexpr ) -> ( & keyexpr , Option < & keyexpr > ) {
441
- match key_expr. as_bytes ( ) . iter ( ) . position ( |c| * c == b'/' ) {
442
- Some ( pos) => {
443
- let left = & key_expr. as_bytes ( ) [ ..pos] ;
444
- let right = & key_expr. as_bytes ( ) [ pos + 1 ..] ;
445
- unsafe {
446
- (
447
- keyexpr:: from_slice_unchecked ( left) ,
448
- Some ( keyexpr:: from_slice_unchecked ( right) ) ,
449
- )
450
- }
451
- }
452
- None => ( key_expr, None ) ,
391
+ /// Split the suffix at the next '/' (after leading one), returning None if the suffix is empty.
392
+ ///
393
+ /// Suffix usually starts with '/', so this first slash is kept as part of the split chunk.
394
+ /// The rest will contain the slash of the split.
395
+ /// For example `split_first_chunk("/a/b") == Some(("/a", "/b"))`.
396
+ fn split_first_chunk ( suffix : & str ) -> Option < ( & str , & str ) > {
397
+ if suffix. is_empty ( ) {
398
+ return None ;
453
399
}
400
+ // don't count the first char which may be a leading slash to find the next one
401
+ Some ( match suffix[ 1 ..] . find ( '/' ) {
402
+ // don't forget to add 1 to the index because of `[1..]` slice above
403
+ Some ( idx) => suffix. split_at ( idx + 1 ) ,
404
+ None => ( suffix, "" ) ,
405
+ } )
454
406
}
455
407
456
408
#[ inline]
@@ -524,7 +476,17 @@ impl Resource {
524
476
}
525
477
}
526
478
479
+ /// Return the best locally/remotely declared keyexpr, i.e. with the smallest suffix, matching
480
+ /// the given suffix and session id.
481
+ ///
482
+ /// The goal is to save bandwidth by using the shortest keyexpr on the wire. It works by
483
+ /// recursively walk through the children tree, looking for an already declared keyexpr for the
484
+ /// session.
485
+ /// If none is found, and if the tested resource itself doesn't have a declared keyexpr,
486
+ /// then the parent tree is walked through. If there is still no declared keyexpr, the whole
487
+ /// prefix+suffix string is used.
527
488
pub fn get_best_key < ' a > ( & self , suffix : & ' a str , sid : usize ) -> WireExpr < ' a > {
489
+ /// Retrieve a declared keyexpr, either local or remote.
528
490
fn get_wire_expr < ' a > (
529
491
prefix : & Resource ,
530
492
suffix : impl FnOnce ( ) -> Cow < ' a , str > ,
@@ -542,19 +504,18 @@ impl Resource {
542
504
mapping,
543
505
} )
544
506
}
507
+ /// Walk through the children tree, looking for a declared keyexpr.
545
508
fn get_best_child_key < ' a > (
546
509
prefix : & Resource ,
547
510
suffix : & ' a str ,
548
511
sid : usize ,
549
512
) -> Option < WireExpr < ' a > > {
550
- if suffix. is_empty ( ) {
551
- return None ;
552
- }
553
- let ( chunk, remain) = suffix. split_at ( suffix. find ( '/' ) . unwrap_or ( suffix. len ( ) ) ) ;
513
+ let ( chunk, rest) = Resource :: split_first_chunk ( suffix) ?;
554
514
let child = prefix. children . get ( chunk) ?;
555
- get_best_child_key ( child, remain , sid)
556
- . or_else ( || get_wire_expr ( child, || remain . into ( ) , sid) )
515
+ get_best_child_key ( child, rest , sid)
516
+ . or_else ( || get_wire_expr ( child, || rest . into ( ) , sid) )
557
517
}
518
+ /// Walk through the parent tree, looking for a declared keyexpr.
558
519
fn get_best_parent_key < ' a > (
559
520
prefix : & Resource ,
560
521
suffix : & ' a str ,
@@ -597,11 +558,20 @@ impl Resource {
597
558
. unwrap_or ( & from. suffix )
598
559
. try_into ( )
599
560
. unwrap ( ) ;
600
- let ( chunk, rest) = Resource :: fst_chunk ( key_expr) ;
601
- if chunk. intersects ( suffix) {
602
- match rest {
561
+ let ( ke_chunk, ke_rest) = match key_expr. split_once ( '/' ) {
562
+ // SAFETY: chunks of keyexpr are valid keyexprs
563
+ Some ( ( chunk, rest) ) => unsafe {
564
+ (
565
+ keyexpr:: from_str_unchecked ( chunk) ,
566
+ Some ( keyexpr:: from_str_unchecked ( rest) ) ,
567
+ )
568
+ } ,
569
+ None => ( key_expr, None ) ,
570
+ } ;
571
+ if ke_chunk. intersects ( suffix) {
572
+ match ke_rest {
603
573
None => {
604
- if chunk . as_bytes ( ) == b"**" {
574
+ if ke_chunk . as_bytes ( ) == b"**" {
605
575
recursive_push ( from, matches)
606
576
} else {
607
577
if from. context . is_some ( ) {
@@ -624,7 +594,7 @@ impl Resource {
624
594
Some ( rest) if rest. as_bytes ( ) == b"**" => recursive_push ( from, matches) ,
625
595
Some ( rest) => {
626
596
let recheck_keyexpr_one_level_lower =
627
- chunk . as_bytes ( ) == b"**" || suffix. as_bytes ( ) == b"**" ;
597
+ ke_chunk . as_bytes ( ) == b"**" || suffix. as_bytes ( ) == b"**" ;
628
598
for child in from. children . values ( ) {
629
599
get_matches_from ( rest, child, matches) ;
630
600
if recheck_keyexpr_one_level_lower {
0 commit comments