@@ -26,6 +26,7 @@ use core::{
26
26
/// * Longer than 23 bytes, but substrings of `WS` (see below). Such strings consist
27
27
/// solely of consecutive newlines, followed by consecutive spaces
28
28
/// * If a string does not satisfy the aforementioned conditions, it is heap-allocated
29
+ /// * Additionally, a `SmolStr` can be explicitely created from a `&'static str` without allocation
29
30
///
30
31
/// Unlike `String`, however, `SmolStr` is immutable. The primary use case for
31
32
/// `SmolStr` is a good enough default storage for tokens of typical programming
@@ -78,6 +79,17 @@ impl SmolStr {
78
79
} )
79
80
}
80
81
82
+ /// Constructs a `SmolStr` from a statically allocated string.
83
+ ///
84
+ /// This never allocates.
85
+ #[ inline( always) ]
86
+ pub const fn new_static ( text : & ' static str ) -> SmolStr {
87
+ // NOTE: this never uses the inline storage; if a canonical
88
+ // representation is needed, we could check for `len() < INLINE_CAP`
89
+ // and call `new_inline`, but this would mean an extra branch.
90
+ SmolStr ( Repr :: Static ( text) )
91
+ }
92
+
81
93
pub fn new < T > ( text : T ) -> SmolStr
82
94
where
83
95
T : AsRef < str > ,
@@ -395,6 +407,11 @@ const N_NEWLINES: usize = 32;
395
407
const N_SPACES : usize = 128 ;
396
408
const WS : & str =
397
409
"\n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n " ;
410
+ const _: ( ) = {
411
+ assert ! ( WS . len( ) == N_NEWLINES + N_SPACES ) ;
412
+ assert ! ( WS . as_bytes( ) [ N_NEWLINES - 1 ] == b'\n' ) ;
413
+ assert ! ( WS . as_bytes( ) [ N_NEWLINES ] == b' ' ) ;
414
+ } ;
398
415
399
416
#[ derive( Clone , Copy , Debug ) ]
400
417
#[ repr( u8 ) ]
@@ -428,18 +445,15 @@ enum InlineSize {
428
445
#[ derive( Clone , Debug ) ]
429
446
enum Repr {
430
447
Heap ( Arc < str > ) ,
448
+ Static ( & ' static str ) ,
431
449
Inline {
432
450
len : InlineSize ,
433
451
buf : [ u8 ; INLINE_CAP ] ,
434
452
} ,
435
- Substring {
436
- newlines : usize ,
437
- spaces : usize ,
438
- } ,
439
453
}
440
454
441
455
impl Repr {
442
- /// This function tries to create a new Repr::Inline or Repr::Substring
456
+ /// This function tries to create a new Repr::Inline or Repr::Static
443
457
/// If it isn't possible, this function returns None
444
458
fn new_on_stack < T > ( text : T ) -> Option < Self >
445
459
where
@@ -467,7 +481,8 @@ impl Repr {
467
481
let possible_space_count = len - newlines;
468
482
if possible_space_count <= N_SPACES && bytes[ newlines..] . iter ( ) . all ( |& b| b == b' ' ) {
469
483
let spaces = possible_space_count;
470
- return Some ( Repr :: Substring { newlines, spaces } ) ;
484
+ let substring = & WS [ N_NEWLINES - newlines..N_NEWLINES + spaces] ;
485
+ return Some ( Repr :: Static ( substring) ) ;
471
486
}
472
487
}
473
488
None
@@ -484,36 +499,30 @@ impl Repr {
484
499
fn len ( & self ) -> usize {
485
500
match self {
486
501
Repr :: Heap ( data) => data. len ( ) ,
502
+ Repr :: Static ( data) => data. len ( ) ,
487
503
Repr :: Inline { len, .. } => * len as usize ,
488
- Repr :: Substring { newlines, spaces } => * newlines + * spaces,
489
504
}
490
505
}
491
506
492
507
#[ inline( always) ]
493
508
fn is_empty ( & self ) -> bool {
494
509
match self {
495
510
Repr :: Heap ( data) => data. is_empty ( ) ,
511
+ Repr :: Static ( data) => data. is_empty ( ) ,
496
512
Repr :: Inline { len, .. } => * len as u8 == 0 ,
497
- // A substring isn't created for an empty string.
498
- Repr :: Substring { .. } => false ,
499
513
}
500
514
}
501
515
502
516
#[ inline]
503
517
fn as_str ( & self ) -> & str {
504
518
match self {
505
519
Repr :: Heap ( data) => & * data,
520
+ Repr :: Static ( data) => data,
506
521
Repr :: Inline { len, buf } => {
507
522
let len = * len as usize ;
508
523
let buf = & buf[ ..len] ;
509
524
unsafe { :: core:: str:: from_utf8_unchecked ( buf) }
510
525
}
511
- Repr :: Substring { newlines, spaces } => {
512
- let newlines = * newlines;
513
- let spaces = * spaces;
514
- assert ! ( newlines <= N_NEWLINES && spaces <= N_SPACES ) ;
515
- & WS [ N_NEWLINES - newlines..N_NEWLINES + spaces]
516
- }
517
526
}
518
527
}
519
528
}
0 commit comments