weakauras_codec_base64/decode/arch/x86_64/
mod.rs1pub mod avx2;
5pub mod sse41;
6
7#[allow(unused_imports)]
8use crate::{decode::scalar, macros::unsafe_runtime_dispatch};
9#[allow(unused_imports)]
10use core::mem::MaybeUninit;
11
12#[cfg(target_feature = "avx2")]
13pub use avx2::decode_into_unchecked;
14
15#[cfg(all(target_feature = "sse4.1", not(target_feature = "avx2")))]
17#[inline(always)]
18pub unsafe fn decode_into_unchecked(
19 input: &[u8],
20 output: &mut [MaybeUninit<u8>],
21) -> Result<usize, usize> {
22 unsafe_runtime_dispatch!(
23 decode_into_unchecked,
24 Result<usize, usize>,
25 input,
26 output,
27 is_x86_feature_detected,
28 ("avx2", avx2),
29 sse41,
30 )
31}
32
33#[cfg(not(any(target_feature = "sse4.1", target_feature = "avx2")))]
35#[inline(always)]
36pub unsafe fn decode_into_unchecked(
37 input: &[u8],
38 output: &mut [MaybeUninit<u8>],
39) -> Result<usize, usize> {
40 unsafe_runtime_dispatch!(
41 decode_into_unchecked,
42 Result<usize, usize>,
43 input,
44 output,
45 is_x86_feature_detected,
46 ("avx2", avx2),
47 ("sse4.1", sse41),
48 scalar,
49 )
50}
51
52#[cfg(test)]
53mod tests {
54 #![allow(unused_imports)]
55 use super::*;
56 use crate::decode::tests::*;
57
58 use alloc::vec::Vec;
59
60 #[test]
61 #[cfg(target_feature = "sse4.1")]
62 fn scalar_and_sse41_return_same_values() {
63 let data: Vec<u8> = base64_iter().take(1024 * 1024 + 3).collect();
64
65 let capacity = data.len() * 3 / 4;
66 let mut buf1 = Vec::with_capacity(capacity);
67 let mut buf2 = Vec::with_capacity(capacity);
68
69 unsafe {
70 let scalar_len =
71 scalar::decode_into_unchecked(&data, buf1.spare_capacity_mut()).unwrap();
72 buf1.set_len(scalar_len);
73
74 let sse41_len = sse41::decode_into_unchecked(&data, buf2.spare_capacity_mut()).unwrap();
75 buf2.set_len(sse41_len);
76 }
77
78 assert_eq!(buf1, buf2);
79 }
80
81 #[test]
82 #[cfg(target_feature = "avx2")]
83 fn scalar_and_avx2_return_same_values() {
84 let data: Vec<u8> = base64_iter().take(1024 * 1024 + 3).collect();
85
86 let capacity = data.len() * 3 / 4;
87 let mut buf1 = Vec::with_capacity(capacity);
88 let mut buf2 = Vec::with_capacity(capacity);
89
90 unsafe {
91 let scalar_len =
92 scalar::decode_into_unchecked(&data, buf1.spare_capacity_mut()).unwrap();
93 buf1.set_len(scalar_len);
94
95 let avx2_len = avx2::decode_into_unchecked(&data, buf2.spare_capacity_mut()).unwrap();
96 buf2.set_len(avx2_len);
97 }
98
99 assert_eq!(buf1, buf2);
100 }
101
102 #[test]
103 #[cfg(target_feature = "sse4.1")]
104 fn sse41_returns_index_of_invalid_byte() {
105 let test_cases = [
106 (
107 core::iter::once(b'=')
108 .chain(base64_iter().take(39))
109 .collect::<Vec<_>>(),
110 0usize,
111 ), (
113 base64_iter()
114 .take(1)
115 .chain(core::iter::once(b'='))
116 .chain(base64_iter().take(38))
117 .collect::<Vec<_>>(),
118 1,
119 ), (
121 base64_iter()
122 .take(16)
123 .chain(core::iter::once(b'='))
124 .chain(base64_iter().take(23))
125 .collect::<Vec<_>>(),
126 16,
127 ), (
129 base64_iter()
130 .take(35)
131 .chain(core::iter::once(b'='))
132 .chain(base64_iter().take(4))
133 .collect::<Vec<_>>(),
134 35,
135 ), ];
137
138 for (data, invalid_byte_at) in test_cases {
139 let capacity = data.len() * 3 / 4;
140 let mut buf = Vec::with_capacity(capacity);
141
142 let result = unsafe { sse41::decode_into_unchecked(&data, buf.spare_capacity_mut()) };
143
144 assert_eq!(result, Err(invalid_byte_at));
145 }
146 }
147
148 #[test]
149 #[cfg(target_feature = "avx2")]
150 fn avx2_returns_index_of_invalid_byte() {
151 let test_cases = [
152 (
153 core::iter::once(b'=')
154 .chain(base64_iter().take(79))
155 .collect::<Vec<_>>(),
156 0usize,
157 ), (
159 base64_iter()
160 .take(1)
161 .chain(core::iter::once(b'='))
162 .chain(base64_iter().take(78))
163 .collect::<Vec<_>>(),
164 1,
165 ), (
167 base64_iter()
168 .take(32)
169 .chain(core::iter::once(b'='))
170 .chain(base64_iter().take(47))
171 .collect::<Vec<_>>(),
172 32,
173 ), (
175 base64_iter()
176 .take(70)
177 .chain(core::iter::once(b'='))
178 .chain(base64_iter().take(9))
179 .collect::<Vec<_>>(),
180 70,
181 ), ];
183
184 for (data, invalid_byte_at) in test_cases {
185 let capacity = data.len() * 3 / 4;
186 let mut buf = Vec::with_capacity(capacity);
187
188 let result = unsafe { avx2::decode_into_unchecked(&data, buf.spare_capacity_mut()) };
189
190 assert_eq!(result, Err(invalid_byte_at));
191 }
192 }
193}