1use rand::Rng;
4use rand::SeedableRng;
5use rand_chacha::ChaCha8Rng;
6
7use crate::ALPHABET_SIZE;
8
9#[derive(Clone, Debug)]
11pub struct Sequence {
12 pub(crate) data: Vec<u8>,
13 pub(crate) alphabet: Vec<u8>,
14 pub(crate) alphabet_size: u32,
15}
16
17impl Sequence {
18 pub fn new() -> Self {
19 Self {
20 data: Vec::new(),
21 alphabet: Vec::new(),
22 alphabet_size: ALPHABET_SIZE,
23 }
24 }
25
26 pub fn with_capacity(cap: usize) -> Self {
27 Self {
28 data: Vec::with_capacity(cap),
29 alphabet: Vec::new(),
30 alphabet_size: ALPHABET_SIZE,
31 }
32 }
33
34 #[allow(clippy::should_implement_trait)]
37 pub fn from_str(s: &str) -> Self {
38 let mut seq = Self {
39 data: s.as_bytes().to_vec(),
40 alphabet: Vec::new(),
41 alphabet_size: ALPHABET_SIZE,
42 };
43 seq.determine_alphabet();
44 seq
45 }
46
47 pub fn from_bytes(b: Vec<u8>) -> Self {
48 let mut seq = Self {
49 data: b,
50 alphabet: Vec::new(),
51 alphabet_size: ALPHABET_SIZE,
52 };
53 seq.determine_alphabet();
54 seq
55 }
56
57 pub fn from_bytes_with_alphabet(b: Vec<u8>, alphabet_size: u32) -> Self {
58 let mut seq = Self {
59 data: b,
60 alphabet: Vec::new(),
61 alphabet_size,
62 };
63 seq.determine_alphabet();
64 seq
65 }
66
67 pub fn with_alphabet_size(alphabet_size: u32) -> Self {
68 Self {
69 data: Vec::new(),
70 alphabet: Vec::new(),
71 alphabet_size,
72 }
73 }
74
75 pub fn as_bytes(&self) -> &[u8] {
76 &self.data
77 }
78
79 pub fn as_bytes_mut(&mut self) -> &mut [u8] {
80 &mut self.data
81 }
82
83 pub fn to_string_lossy(&self) -> String {
84 String::from_utf8_lossy(&self.data).into_owned()
85 }
86
87 pub fn alphabet(&self) -> &[u8] {
88 &self.alphabet
89 }
90
91 pub fn alphabet_size(&self) -> u32 {
92 self.alphabet_size
93 }
94
95 pub fn set_alphabet_size(&mut self, s: u32) {
96 self.alphabet_size = s;
97 }
98
99 pub fn len(&self) -> usize {
100 self.data.len()
101 }
102
103 pub fn is_empty(&self) -> bool {
104 self.data.is_empty()
105 }
106
107 pub fn determine_alphabet(&mut self) -> Vec<u8> {
110 let mut seen = [false; 256];
111 for &c in &self.data {
112 seen[c as usize] = true;
113 }
114 let mut alph = Vec::with_capacity(64);
115 for i in (0..=255u16).rev() {
116 if seen[i as usize] {
117 alph.push(i as u8);
118 }
119 }
120 if alph.len() as u32 != self.alphabet_size {
121 self.alphabet_size = if alph.len() < 2 { 2 } else { alph.len() as u32 };
122 }
123 self.alphabet = alph.clone();
124 alph
125 }
126
127 pub fn push(&mut self, c: u8) -> usize {
128 self.data.push(c);
129 self.data.len()
130 }
131
132 pub fn pop(&mut self) -> usize {
133 self.data.pop();
134 self.data.len()
135 }
136
137 pub fn clear(&mut self) {
138 self.alphabet_size = ALPHABET_SIZE;
139 self.data.clear();
140 }
141
142 pub fn get(&self, idx: usize) -> Option<u8> {
143 self.data.get(idx).copied()
144 }
145
146 pub fn first(&self) -> Option<u8> {
147 self.data.first().copied()
148 }
149
150 pub fn last(&self) -> Option<u8> {
151 self.data.last().copied()
152 }
153
154 pub fn min_byte(&self) -> Option<u8> {
155 self.data.iter().copied().min()
156 }
157
158 pub fn max_byte(&self) -> Option<u8> {
159 self.data.iter().copied().max()
160 }
161
162 pub fn min_range(&self, start: usize, end: usize) -> Option<u8> {
163 self.data
164 .get(start..end)
165 .and_then(|s| s.iter().copied().min())
166 }
167
168 pub fn max_range(&self, start: usize, end: usize) -> Option<u8> {
169 self.data
170 .get(start..end)
171 .and_then(|s| s.iter().copied().max())
172 }
173
174 pub fn take(&self, l: usize) -> Self {
176 let n = l.min(self.data.len());
177 Sequence::from_bytes_with_alphabet(self.data[..n].to_vec(), self.alphabet_size)
178 }
179
180 pub fn drop(&self, l: usize) -> Self {
182 if l >= self.data.len() {
183 return Sequence::with_alphabet_size(self.alphabet_size);
184 }
185 Sequence::from_bytes_with_alphabet(self.data[l..].to_vec(), self.alphabet_size)
186 }
187
188 pub fn split_at(&self, l: usize) -> (Self, Self) {
190 let n = l.min(self.data.len());
191 (
192 Sequence::from_bytes_with_alphabet(self.data[..n].to_vec(), self.alphabet_size),
193 Sequence::from_bytes_with_alphabet(self.data[n..].to_vec(), self.alphabet_size),
194 )
195 }
196
197 pub fn granularity(&self, gr: u32) -> Self {
199 if gr == 0 {
200 return Self::new();
201 }
202 let mut buf = Vec::with_capacity(self.data.len() / gr as usize);
203 let mut seen = [false; 256];
204 let mut temp: u8 = 0;
205 let mut count: u32 = 0;
206 for &c in &self.data {
207 temp = temp.wrapping_add(c);
208 count += 1;
209 if count == gr {
210 buf.push(temp);
211 seen[temp as usize] = true;
212 temp = 0;
213 count = 0;
214 }
215 }
216 let unique = seen.iter().filter(|b| **b).count() as u32;
217 Sequence::from_bytes_with_alphabet(buf, unique)
218 }
219
220 pub fn reverse(&mut self) -> &mut Self {
221 self.data.reverse();
222 self
223 }
224
225 pub fn reverse_copy(&self) -> Self {
226 let mut s = self.clone();
227 s.data.reverse();
228 s
229 }
230
231 pub fn pi(&mut self) -> &mut Self {
232 self.data.pop();
233 self
234 }
235
236 pub fn right_shift(&mut self, ls: u32) -> &mut Self {
237 if self.data.is_empty() {
238 return self;
239 }
240 let shift = (ls as usize) % self.data.len();
241 if shift == 0 {
242 return self;
243 }
244 self.data.rotate_left(shift);
247 self
248 }
249
250 pub fn left_shift(&mut self, ls: u32) -> &mut Self {
251 if self.data.is_empty() {
252 return self;
253 }
254 let n = self.data.len();
255 let shift = n - ((ls as usize) % n);
256 if shift == n {
257 return self;
258 }
259 self.data.rotate_left(shift);
260 self
261 }
262
263 pub fn char_density(&self) -> std::collections::BTreeMap<u8, u32> {
265 let mut m = std::collections::BTreeMap::new();
266 for &c in &self.data {
267 *m.entry(c).or_insert(0u32) += 1;
268 }
269 m
270 }
271
272 pub fn map<F: Fn(u8) -> u8>(&self, f: F) -> Self {
274 let mut data = Vec::with_capacity(self.data.len());
275 for &c in &self.data {
276 data.push(f(c));
277 }
278 Self {
279 data,
280 alphabet: Vec::new(),
281 alphabet_size: self.alphabet_size,
282 }
283 }
284
285 pub fn extend_from_slice(&mut self, other: &[u8]) {
286 self.data.extend_from_slice(other);
287 }
288
289 pub fn xor_with(&mut self, other: &Sequence) -> Result<(), &'static str> {
291 if self.data.len() != other.data.len() {
292 return Err("SequenceNoMatchSize");
293 }
294 for i in 0..self.data.len() {
295 self.data[i] = if self.data[i] == other.data[i] { 0 } else { 1 };
296 }
297 Ok(())
298 }
299}
300
301impl Default for Sequence {
302 fn default() -> Self {
303 Self::new()
304 }
305}
306
307impl std::cmp::PartialEq for Sequence {
308 fn eq(&self, other: &Self) -> bool {
309 self.data == other.data
310 }
311}
312
313impl std::cmp::Eq for Sequence {}
314
315impl std::cmp::PartialOrd for Sequence {
316 fn partial_cmp(&self, other: &Self) -> Option<std::cmp::Ordering> {
317 Some(self.cmp(other))
318 }
319}
320
321impl std::cmp::Ord for Sequence {
322 fn cmp(&self, other: &Self) -> std::cmp::Ordering {
323 self.data.cmp(&other.data)
324 }
325}
326
327impl std::ops::Add for &Sequence {
328 type Output = Sequence;
329 fn add(self, rhs: &Sequence) -> Sequence {
330 let mut data = Vec::with_capacity(self.data.len() + rhs.data.len());
331 data.extend_from_slice(&self.data);
332 data.extend_from_slice(&rhs.data);
333 Sequence {
334 data,
335 alphabet: Vec::new(),
336 alphabet_size: self.alphabet_size.max(rhs.alphabet_size),
337 }
338 }
339}
340
341pub fn shuffle_in_place(s: &mut Sequence, block_size: u32, rng: &mut ChaCha8Rng) {
346 let seq_size = s.len();
347 let bs = block_size as usize;
348 if bs == 0 || seq_size <= bs + 1 {
349 return;
350 }
351 let max_block_idx = (seq_size - bs - 1) / bs;
352 if max_block_idx == 0 {
353 return;
354 }
355 let mut op1 = bs * rng.gen_range(0..=max_block_idx);
357 while op1 + bs > seq_size.saturating_sub(1) {
358 op1 = bs * rng.gen_range(0..=max_block_idx);
359 }
360 if seq_size <= 10 {
361 return;
362 }
363 loop {
365 let op2 = bs * rng.gen_range(0..=max_block_idx);
366 let no_overlap = op2 + bs <= op1 || op2 >= op1 + bs;
367 let in_bounds = op2 + bs <= seq_size.saturating_sub(1);
368 if no_overlap && in_bounds {
369 for i in 0..bs {
371 s.data.swap(op1 + i, op2 + i);
372 }
373 return;
374 }
375 }
376}
377
378pub fn shuffle_copy(s: &Sequence, block_size: u32, times: u32) -> Sequence {
380 let mut out = s.clone();
381 let mut rng = ChaCha8Rng::seed_from_u64(deterministic_seed(s, block_size));
382 for _ in 0..times {
383 shuffle_in_place(&mut out, block_size, &mut rng);
384 }
385 out
386}
387
388pub fn shuffle_copy_seeded(s: &Sequence, block_size: u32, times: u32, seed: u64) -> Sequence {
391 let mut out = s.clone();
392 let mut rng = ChaCha8Rng::seed_from_u64(seed);
393 for _ in 0..times {
394 shuffle_in_place(&mut out, block_size, &mut rng);
395 }
396 out
397}
398
399fn deterministic_seed(s: &Sequence, block_size: u32) -> u64 {
400 let mut hash: u64 = 5381;
401 for &c in &s.data {
402 hash = hash.wrapping_mul(33).wrapping_add(c as u64);
403 }
404 hash ^ (block_size as u64).wrapping_mul(0x9E3779B97F4A7C15)
405}
406
407#[cfg(test)]
408mod tests {
409 use super::*;
410
411 #[test]
412 fn from_str_and_take() {
413 let s = Sequence::from_str("hello");
414 assert_eq!(s.len(), 5);
415 assert_eq!(&s.take(3).data[..], b"hel");
416 }
417
418 #[test]
419 fn split_drop_takes_match() {
420 let s = Sequence::from_str("ABRACADABRA");
421 let (l, r) = s.split_at(5);
422 assert_eq!(&l.data[..], b"ABRAC");
423 assert_eq!(&r.data[..], b"ADABRA");
424 assert_eq!(&s.drop(5).data[..], b"ADABRA");
425 assert_eq!(&s.take(5).data[..], b"ABRAC");
426 }
427
428 #[test]
429 fn shifts() {
430 let mut s = Sequence::from_str("ABCDE");
431 s.right_shift(2);
432 assert_eq!(&s.data[..], b"CDEAB");
433 let mut s = Sequence::from_str("ABCDE");
434 s.left_shift(1);
435 assert_eq!(&s.data[..], b"EABCD");
436 }
437
438 #[test]
439 fn alphabet_min_two() {
440 let s = Sequence::from_str("aaaa");
441 assert_eq!(s.alphabet_size(), 2);
442 }
443
444 #[test]
445 fn shuffle_deterministic() {
446 let s = Sequence::from_str(&"01".repeat(200));
447 let a = shuffle_copy_seeded(&s, 3, 5, 42);
448 let b = shuffle_copy_seeded(&s, 3, 5, 42);
449 assert_eq!(a.data, b.data);
450 }
451}