s3p_core/
transform.rs

1//! XOR-слойной трансформ (WH-lite): ин-плейс, точная обратимость, O(n log n).
2//! Не про криптографию — это упаковка данных для «прогрессивной полезности».
3//! Требует длину буфера — степень двойки.
4
5use crate::errors::*;
6
7#[inline]
8fn is_pow2(x: usize) -> bool {
9    x != 0 && (x & (x - 1)) == 0
10}
11
12/// Прямой трансформ: (a, b) -> (a ^ b, a) послойно.
13pub fn xor_layers_forward(buf: &mut [u8]) -> Result<()> {
14    let n = buf.len();
15    if !is_pow2(n) {
16        return Err(S3pError::Invalid(
17            "xor_layers_forward: length must be power of two".into(),
18        ));
19    }
20    let mut step = 1;
21    while step < n {
22        let stride = step * 2;
23        for i in (0..n).step_by(stride) {
24            for j in 0..step {
25                let a = i + j;
26                let b = a + step;
27                let a0 = buf[a];
28                let b0 = buf[b];
29                buf[a] = a0 ^ b0;
30                buf[b] = a0;
31            }
32        }
33        step <<= 1;
34    }
35    Ok(())
36}
37
38/// Обратный трансформ: обратная операция к (a ^ b, a).
39pub fn xor_layers_inverse(buf: &mut [u8]) -> Result<()> {
40    let n = buf.len();
41    if !is_pow2(n) {
42        return Err(S3pError::Invalid(
43            "xor_layers_inverse: length must be power of two".into(),
44        ));
45    }
46    let mut step = n >> 1;
47    while step > 0 {
48        let stride = step * 2;
49        for i in (0..n).step_by(stride) {
50            for j in 0..step {
51                let a = i + j;
52                let b = a + step;
53                // было (x, y) = (a^b, a) -> обратно: (a, b) = (y, x^y)
54                let x = buf[a];
55                let y = buf[b];
56                buf[b] = x ^ y; // b
57                buf[a] = y; // a
58            }
59        }
60        step >>= 1;
61    }
62    Ok(())
63}