1#![cfg_attr(feature = "generic-simd", feature(portable_simd))]
35#![deny(missing_docs)]
36#![cfg_attr(not(feature = "runtime-dispatch-simd"), no_std)]
37
38#[cfg(not(feature = "runtime-dispatch-simd"))]
39use core::mem;
40#[cfg(feature = "runtime-dispatch-simd")]
41use std::mem;
42
43mod naive;
44pub use naive::*;
45mod integer_simd;
46
47#[cfg(any(
48 all(
49 feature = "runtime-dispatch-simd",
50 any(target_arch = "x86", target_arch = "x86_64")
51 ),
52 all(target_arch = "aarch64", target_endian = "little"),
53 target_arch = "wasm32",
54 feature = "generic-simd"
55))]
56mod simd;
57
58pub fn count(haystack: &[u8], needle: u8) -> usize {
68 if haystack.len() >= 32 {
69 #[cfg(all(feature = "runtime-dispatch-simd", target_arch = "x86_64"))]
70 {
71 if is_x86_feature_detected!("avx2") {
72 unsafe {
73 return simd::x86_avx2::chunk_count(haystack, needle);
74 }
75 }
76 }
77
78 #[cfg(feature = "generic-simd")]
79 return simd::generic::chunk_count(haystack, needle);
80 }
81
82 if haystack.len() >= 16 {
83 #[cfg(all(
84 feature = "runtime-dispatch-simd",
85 any(target_arch = "x86", target_arch = "x86_64"),
86 not(feature = "generic-simd")
87 ))]
88 {
89 if is_x86_feature_detected!("sse2") {
90 unsafe {
91 return simd::x86_sse2::chunk_count(haystack, needle);
92 }
93 }
94 }
95 #[cfg(all(
96 target_arch = "aarch64",
97 target_endian = "little",
98 not(feature = "generic-simd")
99 ))]
100 {
101 unsafe {
102 return simd::aarch64::chunk_count(haystack, needle);
103 }
104 }
105
106 #[cfg(target_arch = "wasm32")]
107 {
108 unsafe {
109 return simd::wasm::chunk_count(haystack, needle);
110 }
111 }
112 }
113
114 if haystack.len() >= mem::size_of::<usize>() {
115 return integer_simd::chunk_count(haystack, needle);
116 }
117
118 naive_count(haystack, needle)
119}
120
121pub fn num_chars(utf8_chars: &[u8]) -> usize {
134 if utf8_chars.len() >= 32 {
135 #[cfg(all(feature = "runtime-dispatch-simd", target_arch = "x86_64"))]
136 {
137 if is_x86_feature_detected!("avx2") {
138 unsafe {
139 return simd::x86_avx2::chunk_num_chars(utf8_chars);
140 }
141 }
142 }
143
144 #[cfg(feature = "generic-simd")]
145 return simd::generic::chunk_num_chars(utf8_chars);
146 }
147
148 if utf8_chars.len() >= 16 {
149 #[cfg(all(
150 feature = "runtime-dispatch-simd",
151 any(target_arch = "x86", target_arch = "x86_64"),
152 not(feature = "generic-simd")
153 ))]
154 {
155 if is_x86_feature_detected!("sse2") {
156 unsafe {
157 return simd::x86_sse2::chunk_num_chars(utf8_chars);
158 }
159 }
160 }
161 #[cfg(all(
162 target_arch = "aarch64",
163 target_endian = "little",
164 not(feature = "generic-simd")
165 ))]
166 {
167 unsafe {
168 return simd::aarch64::chunk_num_chars(utf8_chars);
169 }
170 }
171
172 #[cfg(target_arch = "wasm32")]
173 {
174 unsafe {
175 return simd::wasm::chunk_num_chars(utf8_chars);
176 }
177 }
178 }
179
180 if utf8_chars.len() >= mem::size_of::<usize>() {
181 return integer_simd::chunk_num_chars(utf8_chars);
182 }
183
184 naive_num_chars(utf8_chars)
185}