1
- use core:: { hint:: assert_unchecked, slice} ;
2
1
use std:: simd:: {
3
2
cmp:: SimdPartialOrd ,
4
3
num:: { SimdInt , SimdUint } ,
@@ -43,46 +42,37 @@ where
43
42
}
44
43
45
44
trait SimdInputTrait {
46
- fn new ( ptr : * const u8 ) -> Self ;
47
- fn is_ascii ( & self ) -> bool ;
48
- fn new_partial_masked_load ( ptr : * const u8 , len : usize ) -> Self ;
49
- fn new_partial_copy ( ptr : * const u8 , len : usize ) -> Self ;
50
- fn new_partial ( ptr : * const u8 , len : usize ) -> Self
45
+ fn new ( ptr : & [ u8 ] ) -> Self ;
46
+ fn new_partial_masked_load ( slice : & [ u8 ] ) -> Self ;
47
+ fn new_partial_copy ( slice : & [ u8 ] ) -> Self ;
48
+ fn new_partial ( slice : & [ u8 ] ) -> Self
51
49
where
52
50
Self : Sized ,
53
51
{
54
52
if HAS_FAST_MASKED_LOAD {
55
- Self :: new_partial_masked_load ( ptr , len )
53
+ Self :: new_partial_masked_load ( slice )
56
54
} else {
57
- Self :: new_partial_copy ( ptr , len )
55
+ Self :: new_partial_copy ( slice )
58
56
}
59
57
}
58
+ fn is_ascii ( & self ) -> bool ;
60
59
}
61
60
62
61
impl SimdInputTrait for SimdInput < 16 , 4 > {
63
62
#[ inline]
64
- fn new ( ptr : * const u8 ) -> Self {
65
- #[ expect( clippy:: cast_ptr_alignment) ]
66
- let ptr = ptr. cast :: < u8x16 > ( ) ;
67
- unsafe {
68
- Self {
69
- vals : [
70
- ptr. read_unaligned ( ) ,
71
- ptr. add ( 1 ) . read_unaligned ( ) ,
72
- ptr. add ( 2 ) . read_unaligned ( ) ,
73
- ptr. add ( 3 ) . read_unaligned ( ) ,
74
- ] ,
75
- }
63
+ fn new ( s : & [ u8 ] ) -> Self {
64
+ Self {
65
+ vals : [
66
+ u8x16:: from_slice ( & s[ ..16 ] ) ,
67
+ u8x16:: from_slice ( & s[ 16 ..32 ] ) ,
68
+ u8x16:: from_slice ( & s[ 32 ..48 ] ) ,
69
+ u8x16:: from_slice ( & s[ 48 ..64 ] ) ,
70
+ ] ,
76
71
}
77
72
}
78
73
79
74
#[ inline]
80
- fn new_partial_masked_load ( ptr : * const u8 , len : usize ) -> Self {
81
- unsafe {
82
- assert_unchecked ( len > 0 ) ;
83
- assert_unchecked ( len < 64 ) ;
84
- }
85
- let mut slice = unsafe { slice:: from_raw_parts ( ptr, len) } ;
75
+ fn new_partial_masked_load ( mut slice : & [ u8 ] ) -> Self {
86
76
let val0 = load_masked_opt ( slice) ;
87
77
slice = & slice[ slice. len ( ) . min ( 16 ) ..] ;
88
78
if slice. is_empty ( ) {
@@ -111,12 +101,10 @@ impl SimdInputTrait for SimdInput<16, 4> {
111
101
}
112
102
113
103
#[ inline]
114
- fn new_partial_copy ( ptr : * const u8 , len : usize ) -> Self {
104
+ fn new_partial_copy ( slice : & [ u8 ] ) -> Self {
115
105
let mut buf = [ 0 ; 64 ] ;
116
- unsafe {
117
- ptr. copy_to_nonoverlapping ( buf. as_mut_ptr ( ) , len) ;
118
- }
119
- Self :: new ( buf. as_ptr ( ) )
106
+ buf[ ..slice. len ( ) ] . copy_from_slice ( slice) ;
107
+ Self :: new ( & buf)
120
108
}
121
109
122
110
#[ inline]
@@ -128,7 +116,7 @@ impl SimdInputTrait for SimdInput<16, 4> {
128
116
#[ inline]
129
117
fn load_masked_opt ( slice : & [ u8 ] ) -> Simd < u8 , 16 > {
130
118
if slice. len ( ) > 15 {
131
- unsafe { slice . as_ptr ( ) . cast :: < u8x16 > ( ) . read_unaligned ( ) }
119
+ u8x16 :: from_slice ( & slice [ .. 16 ] )
132
120
} else {
133
121
u8x16:: load_or_default ( slice)
134
122
}
@@ -552,19 +540,15 @@ where
552
540
// WORKAROUND
553
541
// necessary because the for loop is not unrolled on ARM64
554
542
if input. vals . len ( ) == 2 {
555
- unsafe {
556
- self . check_bytes ( * input. vals . as_ptr ( ) ) ;
557
- self . check_bytes ( * input. vals . as_ptr ( ) . add ( 1 ) ) ;
558
- self . incomplete = Self :: is_incomplete ( * input. vals . as_ptr ( ) . add ( 1 ) ) ;
559
- }
543
+ self . check_bytes ( input. vals [ 0 ] ) ;
544
+ self . check_bytes ( input. vals [ 1 ] ) ;
545
+ self . incomplete = Self :: is_incomplete ( input. vals [ 1 ] ) ;
560
546
} else if input. vals . len ( ) == 4 {
561
- unsafe {
562
- self . check_bytes ( * input. vals . as_ptr ( ) ) ;
563
- self . check_bytes ( * input. vals . as_ptr ( ) . add ( 1 ) ) ;
564
- self . check_bytes ( * input. vals . as_ptr ( ) . add ( 2 ) ) ;
565
- self . check_bytes ( * input. vals . as_ptr ( ) . add ( 3 ) ) ;
566
- self . incomplete = Self :: is_incomplete ( * input. vals . as_ptr ( ) . add ( 3 ) ) ;
567
- }
547
+ self . check_bytes ( input. vals [ 0 ] ) ;
548
+ self . check_bytes ( input. vals [ 1 ] ) ;
549
+ self . check_bytes ( input. vals [ 2 ] ) ;
550
+ self . check_bytes ( input. vals [ 3 ] ) ;
551
+ self . incomplete = Self :: is_incomplete ( input. vals [ 3 ] ) ;
568
552
} else {
569
553
panic ! ( "Unsupported number of chunks" ) ;
570
554
}
@@ -578,28 +562,22 @@ where
578
562
#[ inline]
579
563
pub fn validate_utf8_basic ( input : & [ u8 ] ) -> core:: result:: Result < ( ) , basic:: Utf8Error > {
580
564
use crate :: implementation:: helpers:: SIMD_CHUNK_SIZE ;
581
- let len = input. len ( ) ;
582
565
let mut algorithm = Self :: new ( ) ;
583
- let mut idx: usize = 0 ;
584
- let iter_lim = len - ( len % SIMD_CHUNK_SIZE ) ;
585
-
586
- while idx < iter_lim {
587
- let simd_input = unsafe { SimdInput :: < N , O > :: new ( input. as_ptr ( ) . add ( idx) ) } ;
588
- idx += SIMD_CHUNK_SIZE ;
566
+ let mut chunks = input. chunks_exact ( SIMD_CHUNK_SIZE ) ;
567
+ for chunk in chunks. by_ref ( ) {
568
+ let simd_input = SimdInput :: < N , O > :: new ( chunk) ;
589
569
if !simd_input. is_ascii ( ) {
590
570
algorithm. check_block ( & simd_input) ;
591
571
break ;
592
572
}
593
573
}
594
-
595
- while idx < iter_lim {
596
- let input = unsafe { SimdInput :: < N , O > :: new ( input. as_ptr ( ) . add ( idx) ) } ;
597
- algorithm. check_utf8 ( & input) ;
598
- idx += SIMD_CHUNK_SIZE ;
574
+ for chunk in chunks. by_ref ( ) {
575
+ let simd_input = SimdInput :: < N , O > :: new ( chunk) ;
576
+ algorithm. check_utf8 ( & simd_input) ;
599
577
}
600
-
601
- if idx < len {
602
- let simd_input = unsafe { SimdInput :: new_partial ( input . as_ptr ( ) . add ( idx ) , len - idx ) } ;
578
+ let rem = chunks . remainder ( ) ;
579
+ if !rem . is_ascii ( ) {
580
+ let simd_input = SimdInput :: < N , O > :: new_partial ( rem ) ;
603
581
algorithm. check_utf8 ( & simd_input) ;
604
582
}
605
583
algorithm. check_incomplete_pending ( ) ;
0 commit comments