base64_simd/
heap.rs
1use crate::decode::decoded_length;
2use crate::encode::encoded_length_unchecked;
3use crate::{AppendBase64Decode, AppendBase64Encode};
4use crate::{Base64, Error};
5use crate::{FromBase64Decode, FromBase64Encode};
6
7use vsimd::tools::{alloc_uninit_bytes, assume_init, boxed_str, slice_parts};
8
9use alloc::boxed::Box;
10use alloc::string::String;
11use alloc::vec::Vec;
12
13#[inline]
14fn encode_to_boxed_str(base64: &Base64, data: &[u8]) -> Box<str> {
15 if data.is_empty() {
16 return Box::from("");
17 }
18
19 unsafe {
20 let m = encoded_length_unchecked(data.len(), base64.config);
21 assert!(m <= usize::MAX / 2);
22
23 let mut buf = alloc_uninit_bytes(m);
24
25 {
26 let (src, len) = slice_parts(data);
27 let dst: *mut u8 = buf.as_mut_ptr().cast();
28 crate::multiversion::encode::auto(src, len, dst, base64.config);
29 }
30
31 boxed_str(assume_init(buf))
32 }
33}
34
35#[inline]
36fn encode_append_vec(base64: &Base64, src: &[u8], buf: &mut Vec<u8>) {
37 if src.is_empty() {
38 return;
39 }
40
41 unsafe {
42 let m = encoded_length_unchecked(src.len(), base64.config);
43 assert!(m <= usize::MAX / 2);
44
45 buf.reserve_exact(m);
46 let prev_len = buf.len();
47
48 {
49 let (src, len) = slice_parts(src);
50 let dst = buf.as_mut_ptr().add(prev_len);
51 crate::multiversion::encode::auto(src, len, dst, base64.config);
52 }
53
54 buf.set_len(prev_len + m);
55 }
56}
57
58#[inline]
59fn decode_to_boxed_bytes(base64: &Base64, data: &[u8]) -> Result<Box<[u8]>, Error> {
60 if data.is_empty() {
61 return Ok(Box::from([]));
62 }
63
64 unsafe {
65 let (n, m) = decoded_length(data, base64.config)?;
66
67 let mut buf = alloc_uninit_bytes(m);
69
70 {
71 let dst = buf.as_mut_ptr().cast();
72 let src = data.as_ptr();
73 crate::multiversion::decode::auto(src, dst, n, base64.config)?;
74 }
75
76 Ok(assume_init(buf))
77 }
78}
79
80#[inline]
81fn decode_append_vec(base64: &Base64, src: &[u8], buf: &mut Vec<u8>) -> Result<(), Error> {
82 if src.is_empty() {
83 return Ok(());
84 }
85
86 unsafe {
87 let (n, m) = decoded_length(src, base64.config)?;
88
89 buf.reserve_exact(m);
90 let prev_len = buf.len();
91
92 let dst = buf.as_mut_ptr().add(prev_len);
93 let src = src.as_ptr();
94 crate::multiversion::decode::auto(src, dst, n, base64.config)?;
95
96 buf.set_len(prev_len + m);
97 Ok(())
98 }
99}
100
101#[cfg_attr(docsrs, doc(cfg(feature = "alloc")))]
102impl FromBase64Decode for Box<[u8]> {
103 #[inline]
104 fn from_base64_decode(base64: &Base64, data: &[u8]) -> Result<Self, Error> {
105 decode_to_boxed_bytes(base64, data)
106 }
107}
108
109#[cfg_attr(docsrs, doc(cfg(feature = "alloc")))]
110impl FromBase64Decode for Vec<u8> {
111 #[inline]
112 fn from_base64_decode(base64: &Base64, data: &[u8]) -> Result<Self, crate::Error> {
113 let ans = decode_to_boxed_bytes(base64, data)?;
114 Ok(Vec::from(ans))
115 }
116}
117
118#[cfg_attr(docsrs, doc(cfg(feature = "alloc")))]
119impl FromBase64Encode for Box<[u8]> {
120 #[inline]
121 fn from_base64_encode(base64: &Base64, data: &[u8]) -> Self {
122 let ans = encode_to_boxed_str(base64, data);
123 ans.into_boxed_bytes()
124 }
125}
126
127#[cfg_attr(docsrs, doc(cfg(feature = "alloc")))]
128impl FromBase64Encode for Box<str> {
129 #[inline]
130 fn from_base64_encode(base64: &Base64, data: &[u8]) -> Self {
131 encode_to_boxed_str(base64, data)
132 }
133}
134
135#[cfg_attr(docsrs, doc(cfg(feature = "alloc")))]
136impl FromBase64Encode for Vec<u8> {
137 #[inline]
138 fn from_base64_encode(base64: &Base64, data: &[u8]) -> Self {
139 let ans = encode_to_boxed_str(base64, data);
140 Vec::from(ans.into_boxed_bytes())
141 }
142}
143
144#[cfg_attr(docsrs, doc(cfg(feature = "alloc")))]
145impl FromBase64Encode for String {
146 #[inline]
147 fn from_base64_encode(base64: &Base64, data: &[u8]) -> Self {
148 let ans = encode_to_boxed_str(base64, data);
149 String::from(ans)
150 }
151}
152
153#[cfg_attr(docsrs, doc(cfg(feature = "alloc")))]
154impl AppendBase64Encode for Vec<u8> {
155 #[inline]
156 fn append_base64_encode(base64: &Base64, src: &[u8], dst: &mut Self) {
157 encode_append_vec(base64, src, dst);
158 }
159}
160
161#[cfg_attr(docsrs, doc(cfg(feature = "alloc")))]
162impl AppendBase64Encode for String {
163 #[inline]
164 fn append_base64_encode(base64: &Base64, src: &[u8], dst: &mut Self) {
165 unsafe { encode_append_vec(base64, src, dst.as_mut_vec()) };
166 }
167}
168
169#[cfg_attr(docsrs, doc(cfg(feature = "alloc")))]
170impl AppendBase64Decode for Vec<u8> {
171 #[inline]
172 fn append_base64_decode(base64: &Base64, src: &[u8], dst: &mut Self) -> Result<(), Error> {
173 decode_append_vec(base64, src, dst)
174 }
175}