use crate::Key;
use std::cmp::Ordering;
use subtle::{Choice, ConditionallySelectable, ConstantTimeEq};
#[cfg(any(feature = "chrono", feature = "decimal"))]
pub(crate) mod byte_array;
#[cfg(feature = "chrono")]
pub(crate) mod chrono;
#[cfg(feature = "decimal")]
pub(crate) mod decimal;
pub(crate) mod primitives;
pub(crate) mod string;
pub(crate) mod variable;
pub fn encrypt_ope_bits<I>(bits: I, n: usize, key: &Key, salt: Option<&[u8]>) -> Vec<u8>
where
I: IntoIterator<Item = u8>,
{
let mut hasher = blake3::Hasher::new_keyed(&key.0);
if let Some(salt) = salt {
let _ = hasher.update(salt);
}
let mut out: Vec<u8> = Vec::with_capacity(n + 1);
out.push(0);
let mut plain_bits: Vec<u8> = Vec::with_capacity(n);
for bit in bits {
let mut buf: [u8; 16] = [0; 16];
hasher.finalize_xof().fill(&mut buf);
let prf = (u128::from_be_bytes(buf) & 0xFF) as u8;
out.push(prf);
plain_bits.push(bit);
let _ = hasher.update(&[bit]);
}
debug_assert_eq!(plain_bits.len(), n);
let mut carry: u16 = 0;
for (byte, &bit) in out[1..].iter_mut().rev().zip(plain_bits.iter().rev()) {
let sum = *byte as u16 + ((bit as u16) << 7) + carry;
*byte = sum as u8;
carry = sum >> 8;
}
debug_assert!(carry <= 1);
out[0] = carry as u8;
out
}
fn compare_slice(a: &[u8], b: &[u8]) -> Ordering {
assert_eq!(a.len(), b.len());
let mut diff_x: u8 = 0;
let mut diff_y: u8 = 0;
let mut found_diff = Choice::from(0u8);
for (x, y) in a.iter().zip(b.iter()) {
let is_diff = !x.ct_eq(y);
let not_found_yet = !found_diff;
let should_record = is_diff & not_found_yet;
diff_x = u8::conditional_select(&diff_x, x, should_record);
diff_y = u8::conditional_select(&diff_y, y, should_record);
found_diff = Choice::conditional_select(&found_diff, &is_diff, should_record);
}
let is_greater = diff_y.wrapping_add(1).ct_eq(&diff_x);
let is_equal = !found_diff;
if bool::from(is_equal) {
Ordering::Equal
} else if bool::from(is_greater) {
Ordering::Greater
} else {
Ordering::Less
}
}