simdutf8/implementation/x86/
mod.rs

1#[allow(dead_code)]
2pub(crate) mod avx2;
3
4#[allow(dead_code)]
5pub(crate) mod sse42;
6
7#[allow(unused_imports)]
8use super::helpers::SIMD_CHUNK_SIZE;
9
10// validate_utf8_basic() std: implementation auto-selection
11
12#[cfg(all(feature = "std", not(target_feature = "avx2")))]
13#[inline]
14pub(crate) unsafe fn validate_utf8_basic(
15    input: &[u8],
16) -> core::result::Result<(), crate::basic::Utf8Error> {
17    use core::mem;
18    use std::sync::atomic::{AtomicPtr, Ordering};
19
20    type FnRaw = *mut ();
21
22    static FN: AtomicPtr<()> = AtomicPtr::new(get_fastest as FnRaw);
23
24    unsafe fn get_fastest(input: &[u8]) -> core::result::Result<(), crate::basic::Utf8Error> {
25        let fun = get_fastest_available_implementation_basic();
26        FN.store(fun as FnRaw, Ordering::Relaxed);
27        (fun)(input)
28    }
29
30    if input.len() < SIMD_CHUNK_SIZE {
31        return super::validate_utf8_basic_fallback(input);
32    }
33
34    let fun = FN.load(Ordering::Relaxed);
35    mem::transmute::<FnRaw, super::ValidateUtf8Fn>(fun)(input)
36}
37
38#[cfg(all(feature = "std", not(target_feature = "avx2")))]
39#[inline]
40fn get_fastest_available_implementation_basic() -> super::ValidateUtf8Fn {
41    if std::is_x86_feature_detected!("avx2") {
42        avx2::validate_utf8_basic
43    } else if std::is_x86_feature_detected!("sse4.2") {
44        sse42::validate_utf8_basic
45    } else {
46        super::validate_utf8_basic_fallback
47    }
48}
49
50// validate_utf8_basic() no-std: implementation selection by config
51
52#[cfg(target_feature = "avx2")]
53pub(crate) unsafe fn validate_utf8_basic(
54    input: &[u8],
55) -> core::result::Result<(), crate::basic::Utf8Error> {
56    if input.len() < SIMD_CHUNK_SIZE {
57        return super::validate_utf8_basic_fallback(input);
58    }
59
60    validate_utf8_basic_avx2(input)
61}
62
63#[cfg(target_feature = "avx2")]
64#[inline(never)]
65unsafe fn validate_utf8_basic_avx2(
66    input: &[u8],
67) -> core::result::Result<(), crate::basic::Utf8Error> {
68    avx2::validate_utf8_basic(input)
69}
70
71#[cfg(all(
72    not(feature = "std"),
73    not(target_feature = "avx2"),
74    target_feature = "sse4.2"
75))]
76pub(crate) unsafe fn validate_utf8_basic(
77    input: &[u8],
78) -> core::result::Result<(), crate::basic::Utf8Error> {
79    if input.len() < SIMD_CHUNK_SIZE {
80        return super::validate_utf8_basic_fallback(input);
81    }
82
83    validate_utf8_basic_sse42(input)
84}
85
86#[cfg(all(
87    not(feature = "std"),
88    not(target_feature = "avx2"),
89    target_feature = "sse4.2"
90))]
91#[inline(never)]
92unsafe fn validate_utf8_basic_sse42(
93    input: &[u8],
94) -> core::result::Result<(), crate::basic::Utf8Error> {
95    sse42::validate_utf8_basic(input)
96}
97
98#[cfg(all(
99    not(feature = "std"),
100    not(target_feature = "avx2"),
101    not(target_feature = "sse4.2")
102))]
103pub(crate) use super::validate_utf8_basic_fallback as validate_utf8_basic;
104
105// validate_utf8_compat() std: implementation auto-selection
106
107#[cfg(all(feature = "std", not(target_feature = "avx2")))]
108#[cfg(feature = "std")]
109#[inline]
110pub(crate) unsafe fn validate_utf8_compat(
111    input: &[u8],
112) -> core::result::Result<(), crate::compat::Utf8Error> {
113    use core::mem;
114    use std::sync::atomic::{AtomicPtr, Ordering};
115
116    type FnRaw = *mut ();
117
118    static FN: AtomicPtr<()> = AtomicPtr::new(get_fastest as FnRaw);
119
120    unsafe fn get_fastest(input: &[u8]) -> core::result::Result<(), crate::compat::Utf8Error> {
121        let fun = get_fastest_available_implementation_compat();
122        FN.store(fun as FnRaw, Ordering::Relaxed);
123        (fun)(input)
124    }
125
126    if input.len() < SIMD_CHUNK_SIZE {
127        return super::validate_utf8_compat_fallback(input);
128    }
129
130    let fun = FN.load(Ordering::Relaxed);
131    mem::transmute::<FnRaw, super::ValidateUtf8CompatFn>(fun)(input)
132}
133
134#[cfg(all(feature = "std", not(target_feature = "avx2")))]
135#[inline]
136fn get_fastest_available_implementation_compat() -> super::ValidateUtf8CompatFn {
137    if std::is_x86_feature_detected!("avx2") {
138        avx2::validate_utf8_compat
139    } else if std::is_x86_feature_detected!("sse4.2") {
140        sse42::validate_utf8_compat
141    } else {
142        super::validate_utf8_compat_fallback
143    }
144}
145
146// validate_utf8_basic() no-std: implementation selection by config
147
148#[cfg(target_feature = "avx2")]
149pub(crate) unsafe fn validate_utf8_compat(
150    input: &[u8],
151) -> core::result::Result<(), crate::compat::Utf8Error> {
152    if input.len() < SIMD_CHUNK_SIZE {
153        return super::validate_utf8_compat_fallback(input);
154    }
155
156    validate_utf8_compat_avx2(input)
157}
158
159#[cfg(target_feature = "avx2")]
160#[inline(never)]
161unsafe fn validate_utf8_compat_avx2(
162    input: &[u8],
163) -> core::result::Result<(), crate::compat::Utf8Error> {
164    avx2::validate_utf8_compat(input)
165}
166
167#[cfg(all(
168    not(feature = "std"),
169    not(target_feature = "avx2"),
170    target_feature = "sse4.2"
171))]
172pub(crate) unsafe fn validate_utf8_compat(
173    input: &[u8],
174) -> core::result::Result<(), crate::compat::Utf8Error> {
175    if input.len() < SIMD_CHUNK_SIZE {
176        return super::validate_utf8_compat_fallback(input);
177    }
178
179    validate_utf8_compat_sse42(input)
180}
181
182#[cfg(all(
183    not(feature = "std"),
184    not(target_feature = "avx2"),
185    target_feature = "sse4.2"
186))]
187#[inline(never)]
188pub(crate) unsafe fn validate_utf8_compat_sse42(
189    input: &[u8],
190) -> core::result::Result<(), crate::compat::Utf8Error> {
191    sse42::validate_utf8_compat(input)
192}
193
194#[cfg(all(
195    not(feature = "std"),
196    not(target_feature = "avx2"),
197    not(target_feature = "sse4.2")
198))]
199pub(crate) use super::validate_utf8_compat_fallback as validate_utf8_compat;