use crate::errors::{LoopError, OverflowError};
use core::convert::{TryFrom, TryInto};
pub trait StreamCipher {
#[inline]
fn apply_keystream(&mut self, data: &mut [u8]) {
self.try_apply_keystream(data).unwrap();
}
fn try_apply_keystream(&mut self, data: &mut [u8]) -> Result<(), LoopError>;
}
pub trait StreamCipherSeek {
fn try_current_pos<T: SeekNum>(&self) -> Result<T, OverflowError>;
fn try_seek<T: SeekNum>(&mut self, pos: T) -> Result<(), LoopError>;
fn current_pos<T: SeekNum>(&self) -> T {
self.try_current_pos().unwrap()
}
fn seek<T: SeekNum>(&mut self, pos: T) {
self.try_seek(pos).unwrap()
}
}
pub trait AsyncStreamCipher {
fn encrypt(&mut self, data: &mut [u8]);
fn decrypt(&mut self, data: &mut [u8]);
}
impl<C: StreamCipher> StreamCipher for &mut C {
#[inline]
fn apply_keystream(&mut self, data: &mut [u8]) {
C::apply_keystream(self, data);
}
#[inline]
fn try_apply_keystream(&mut self, data: &mut [u8]) -> Result<(), LoopError> {
C::try_apply_keystream(self, data)
}
}
#[rustfmt::skip]
pub trait SeekNum:
Sized
+ TryInto<u8> + TryFrom<u8> + TryInto<i8> + TryFrom<i8>
+ TryInto<u16> + TryFrom<u16> + TryInto<i16> + TryFrom<i16>
+ TryInto<u32> + TryFrom<u32> + TryInto<i32> + TryFrom<i32>
+ TryInto<u64> + TryFrom<u64> + TryInto<i64> + TryFrom<i64>
+ TryInto<u128> + TryFrom<u128> + TryInto<i128> + TryFrom<i128>
+ TryInto<usize> + TryFrom<usize> + TryInto<isize> + TryFrom<isize>
{
fn from_block_byte<T: SeekNum>(block: T, byte: u8, bs: u8) -> Result<Self, OverflowError>;
fn to_block_byte<T: SeekNum>(self, bs: u8) -> Result<(T, u8), OverflowError>;
}
macro_rules! impl_seek_num {
{$($t:ty )*} => {
$(
impl SeekNum for $t {
fn from_block_byte<T: TryInto<Self>>(block: T, byte: u8, bs: u8) -> Result<Self, OverflowError> {
debug_assert!(byte < bs);
let block = block.try_into().map_err(|_| OverflowError)?;
let pos = block.checked_mul(bs as Self).ok_or(OverflowError)? + (byte as Self);
Ok(pos)
}
fn to_block_byte<T: TryFrom<Self>>(self, bs: u8) -> Result<(T, u8), OverflowError> {
let bs = bs as Self;
let byte = self % bs;
let block = T::try_from(self/bs).map_err(|_| OverflowError)?;
Ok((block, byte as u8))
}
}
)*
};
}
impl_seek_num! { u8 u16 u32 u64 u128 usize i32 }