1#[cfg(feature = "alloc")]
2use alloc::vec::Vec;
3
4#[cfg(all(target_arch = "x86_64", not(feature = "paranoid")))]
5use super::CpuTier;
6
7#[inline]
8pub fn append_literals(dst: &mut Vec<u8>, src: &[u8]) {
9 if src.is_empty() {
10 return;
11 }
12
13 #[cfg(not(feature = "paranoid"))]
14 {
15 let len = src.len();
16 dst.reserve(len + 32);
17 let dst_offset = dst.len();
18
19 #[cfg(target_arch = "x86_64")]
20 {
21 let tier = super::cpu_tier();
22 if tier >= CpuTier::Avx2 && len >= 32 {
23 unsafe {
24 let dst_ptr = dst.as_mut_ptr().add(dst_offset);
25 super::x86_64::avx2::wildcopy_avx2(src.as_ptr(), dst_ptr, len);
26 dst.set_len(dst_offset + len);
27 }
28 return;
29 }
30 if tier >= CpuTier::Sse2 && len >= 16 {
31 unsafe {
32 let dst_ptr = dst.as_mut_ptr().add(dst_offset);
33 super::x86_64::sse2::wildcopy_sse2(src.as_ptr(), dst_ptr, len);
34 dst.set_len(dst_offset + len);
35 }
36 return;
37 }
38 }
39
40 #[cfg(target_arch = "aarch64")]
41 {
42 if len >= 16 {
43 unsafe {
44 let dst_ptr = dst.as_mut_ptr().add(dst_offset);
45 super::aarch64::neon::wildcopy_neon(src.as_ptr(), dst_ptr, len);
46 dst.set_len(dst_offset + len);
47 }
48 return;
49 }
50 }
51
52 if len >= 8 {
53 unsafe {
54 let dst_ptr = dst.as_mut_ptr().add(dst_offset);
55 super::scalar::wildcopy_nonoverlap(src.as_ptr(), dst_ptr, len);
56 dst.set_len(dst_offset + len);
57 }
58 } else {
59 dst.extend_from_slice(src);
60 }
61 }
62
63 #[cfg(feature = "paranoid")]
64 dst.extend_from_slice(src);
65}
66
67#[inline]
68pub fn append_match(dst: &mut Vec<u8>, offset: usize, match_length: usize) {
69 if match_length == 0 {
70 return;
71 }
72
73 debug_assert!(offset <= dst.len());
74 debug_assert!(offset > 0);
75
76 #[cfg(not(feature = "paranoid"))]
77 {
78 dst.reserve(match_length + 32);
79 let dst_len = dst.len();
80 unsafe {
81 let base = dst.as_mut_ptr();
82 let write_ptr = base.add(dst_len);
83 super::scalar::copy_match(write_ptr, offset, match_length);
84 dst.set_len(dst_len + match_length);
85 }
86 }
87
88 #[cfg(feature = "paranoid")]
89 {
90 dst.reserve(match_length);
91 let start = dst.len() - offset;
92 if offset >= match_length {
93 let len = dst.len();
94 dst.resize(len + match_length, 0);
95 dst.copy_within(start..start + match_length, len);
96 } else {
97 for i in 0..match_length {
98 let b = dst[start + i % offset];
99 dst.push(b);
100 }
101 }
102 }
103}
104
105#[inline]
106pub fn common_prefix_len(a: &[u8], b: &[u8]) -> usize {
107 #[cfg(all(target_arch = "x86_64", not(feature = "paranoid")))]
108 {
109 let tier = super::cpu_tier();
110 if tier >= CpuTier::Avx2 && a.len() >= 32 && b.len() >= 32 {
111 return unsafe { super::x86_64::avx2::common_prefix_len_avx2(a, b) };
112 }
113 }
114 #[cfg(all(target_arch = "aarch64", not(feature = "paranoid")))]
115 {
116 if a.len() >= 16 && b.len() >= 16 {
117 return unsafe { super::aarch64::neon::common_prefix_len_neon(a, b) };
118 }
119 }
120 super::scalar::common_prefix_len(a, b)
121}
122
123#[inline]
124pub fn append_match_with_history(
125 dst: &mut Vec<u8>,
126 history: &[u8],
127 offset: usize,
128 match_length: usize,
129) {
130 if match_length == 0 {
131 return;
132 }
133
134 let out_len = dst.len();
135
136 if offset <= out_len {
137 append_match(dst, offset, match_length);
138 } else {
139 let history_reach = offset - out_len;
140 let history_start = history.len() - history_reach;
141 let from_history = history_reach.min(match_length);
142
143 dst.extend_from_slice(&history[history_start..history_start + from_history]);
144
145 let remaining = match_length - from_history;
146 if remaining > 0 {
147 append_match(dst, offset, remaining);
148 }
149 }
150}