Coverage Report

Created: 2026-03-31 07:45

next uncovered line (L), next uncovered region (R), next uncovered branch (B)
/rust/registry/src/index.crates.io-1949cf8c6b5b557f/cipher-0.3.0/src/stream.rs
Line
Count
Source
1
//! Traits which define functionality of stream ciphers.
2
//!
3
//! See [RustCrypto/stream-ciphers](https://github.com/RustCrypto/stream-ciphers)
4
//! for ciphers implementation.
5
6
use crate::errors::{LoopError, OverflowError};
7
use core::convert::{TryFrom, TryInto};
8
9
/// Synchronous stream cipher core trait.
10
pub trait StreamCipher {
11
    /// Apply keystream to the data.
12
    ///
13
    /// It will XOR generated keystream with the data, which can be both
14
    /// encryption and decryption.
15
    ///
16
    /// # Panics
17
    /// If end of the keystream will be reached with the given data length,
18
    /// method will panic without modifying the provided `data`.
19
    #[inline]
20
3.59k
    fn apply_keystream(&mut self, data: &mut [u8]) {
21
3.59k
        self.try_apply_keystream(data).unwrap();
22
3.59k
    }
23
24
    /// Apply keystream to the data, but return an error if end of a keystream
25
    /// will be reached.
26
    ///
27
    /// If end of the keystream will be achieved with the given data length,
28
    /// method will return `Err(LoopError)` without modifying provided `data`.
29
    fn try_apply_keystream(&mut self, data: &mut [u8]) -> Result<(), LoopError>;
30
}
31
32
/// Trait for seekable stream ciphers.
33
///
34
/// Methods of this trait are generic over the [`SeekNum`] trait, which is
35
/// implemented for primitive numeric types, i.e.: `i/u8`, `i/u16`, `i/u32`,
36
/// `i/u64`, `i/u128`, and `i/usize`.
37
pub trait StreamCipherSeek {
38
    /// Try to get current keystream position
39
    ///
40
    /// Returns [`LoopError`] if position can not be represented by type `T`
41
    fn try_current_pos<T: SeekNum>(&self) -> Result<T, OverflowError>;
42
43
    /// Try to seek to the given position
44
    ///
45
    /// Returns [`LoopError`] if provided position value is bigger than
46
    /// keystream length.
47
    fn try_seek<T: SeekNum>(&mut self, pos: T) -> Result<(), LoopError>;
48
49
    /// Get current keystream position
50
    ///
51
    /// # Panics
52
    /// If position can not be represented by type `T`
53
    fn current_pos<T: SeekNum>(&self) -> T {
54
        self.try_current_pos().unwrap()
55
    }
56
57
    /// Seek to the given position
58
    ///
59
    /// # Panics
60
    /// If provided position value is bigger than keystream leangth
61
    fn seek<T: SeekNum>(&mut self, pos: T) {
62
        self.try_seek(pos).unwrap()
63
    }
64
}
65
66
/// Asynchronous stream cipher core trait.
67
pub trait AsyncStreamCipher {
68
    /// Encrypt data in place.
69
    fn encrypt(&mut self, data: &mut [u8]);
70
71
    /// Decrypt data in place.
72
    fn decrypt(&mut self, data: &mut [u8]);
73
}
74
75
impl<C: StreamCipher> StreamCipher for &mut C {
76
    #[inline]
77
    fn apply_keystream(&mut self, data: &mut [u8]) {
78
        C::apply_keystream(self, data);
79
    }
80
81
    #[inline]
82
    fn try_apply_keystream(&mut self, data: &mut [u8]) -> Result<(), LoopError> {
83
        C::try_apply_keystream(self, data)
84
    }
85
}
86
87
/// Trait implemented for numeric types which can be used with the
88
/// [`StreamCipherSeek`] trait.
89
///
90
/// This trait is implemented for primitive numeric types, i.e. `i/u8`,
91
/// `u16`, `u32`, `u64`, `u128`, `usize`, and `i32`. It is not intended
92
/// to be implemented in third-party crates.
93
#[rustfmt::skip]
94
pub trait SeekNum:
95
    Sized
96
    + TryInto<u8> + TryFrom<u8> + TryInto<i8> + TryFrom<i8>
97
    + TryInto<u16> + TryFrom<u16> + TryInto<i16> + TryFrom<i16>
98
    + TryInto<u32> + TryFrom<u32> + TryInto<i32> + TryFrom<i32>
99
    + TryInto<u64> + TryFrom<u64> + TryInto<i64> + TryFrom<i64>
100
    + TryInto<u128> + TryFrom<u128> + TryInto<i128> + TryFrom<i128>
101
    + TryInto<usize> + TryFrom<usize> + TryInto<isize> + TryFrom<isize>
102
{
103
    /// Try to get position for block number `block`, byte position inside
104
    /// block `byte`, and block size `bs`.
105
    fn from_block_byte<T: SeekNum>(block: T, byte: u8, bs: u8) -> Result<Self, OverflowError>;
106
107
    /// Try to get block number and bytes position for given block size `bs`.
108
    fn to_block_byte<T: SeekNum>(self, bs: u8) -> Result<(T, u8), OverflowError>;
109
}
110
111
macro_rules! impl_seek_num {
112
    {$($t:ty )*} => {
113
        $(
114
            impl SeekNum for $t {
115
                fn from_block_byte<T: TryInto<Self>>(block: T, byte: u8, bs: u8) -> Result<Self, OverflowError> {
116
                    debug_assert!(byte < bs);
117
                    let block = block.try_into().map_err(|_| OverflowError)?;
118
                    let pos = block.checked_mul(bs as Self).ok_or(OverflowError)? + (byte as Self);
119
                    Ok(pos)
120
                }
121
122
                fn to_block_byte<T: TryFrom<Self>>(self, bs: u8) -> Result<(T, u8), OverflowError> {
123
                    let bs = bs as Self;
124
                    let byte = self % bs;
125
                    let block = T::try_from(self/bs).map_err(|_| OverflowError)?;
126
                    Ok((block, byte as u8))
127
                }
128
            }
129
        )*
130
    };
131
}
132
133
impl_seek_num! { u8 u16 u32 u64 u128 usize i32 }