stun_rs/
algorithm.rs

1use std::sync::Arc;
2
3/// [STUN Password Algorithms](https://datatracker.ietf.org/doc/html/rfc8489#section-18.5)
4#[derive(Debug, PartialEq, Eq, Copy, Clone)]
5pub enum AlgorithmId {
6    /// Reserved
7    Reserved,
8    /// The `MD5` (message-digest algorithm) hashing algorithm is a one-way cryptographic function that accepts a message of any length as input and returns as output a fixed-length digest value to be used for authenticating the original message.
9    MD5,
10    /// `SHA256` is a part of the `SHA` 2 family of algorithms. It stands for Secure Hash Algorithm 256-bit and it is used for cryptographic security.
11    SHA256,
12    /// Unassigned
13    Unassigned(u16),
14}
15
16impl std::fmt::Display for AlgorithmId {
17    fn fmt(&self, f: &mut std::fmt::Formatter) -> std::fmt::Result {
18        match *self {
19            AlgorithmId::Reserved => write!(f, "reserved"),
20            AlgorithmId::MD5 => write!(f, "md5"),
21            AlgorithmId::SHA256 => write!(f, "sha256"),
22            AlgorithmId::Unassigned(val) => write!(f, "unassigned({})", val),
23        }
24    }
25}
26
27impl From<u16> for AlgorithmId {
28    fn from(val: u16) -> Self {
29        match val {
30            0 => AlgorithmId::Reserved,
31            1 => AlgorithmId::MD5,
32            2 => AlgorithmId::SHA256,
33            _ => AlgorithmId::Unassigned(val),
34        }
35    }
36}
37
38impl From<AlgorithmId> for u16 {
39    fn from(val: AlgorithmId) -> Self {
40        match val {
41            AlgorithmId::Reserved => 0,
42            AlgorithmId::MD5 => 1,
43            AlgorithmId::SHA256 => 2,
44            AlgorithmId::Unassigned(val) => val,
45        }
46    }
47}
48
49/// An algorithm is the combination of the [`AlgorithmId`] and its parameters.
50#[derive(Debug, Clone, PartialEq, Eq)]
51pub struct Algorithm {
52    algorithm: AlgorithmId,
53    params: Option<Arc<Vec<u8>>>,
54}
55impl AsRef<Algorithm> for Algorithm {
56    fn as_ref(&self) -> &Algorithm {
57        self
58    }
59}
60
61impl Algorithm {
62    /// Creates a new algorithm with parameters.
63    /// # Attributes:
64    /// * `algorithm` - The [Algorithm].
65    /// * `parameters` - Specific parameters for the algorithm, if any.
66    pub fn new<'a, T>(algorithm: AlgorithmId, parameters: T) -> Self
67    where
68        T: Into<Option<&'a [u8]>>,
69    {
70        Self {
71            algorithm,
72            params: parameters.into().map(Vec::from).map(Arc::new),
73        }
74    }
75
76    /// Returns the algorithm
77    pub fn algorithm(&self) -> AlgorithmId {
78        self.algorithm
79    }
80
81    /// Returns the parameters required by the algorithm.
82    pub fn parameters(&self) -> Option<&[u8]> {
83        self.params.as_ref().map(|v| v.as_ref().as_slice())
84    }
85}
86
87impl From<AlgorithmId> for Algorithm {
88    fn from(algorithm: AlgorithmId) -> Self {
89        Self {
90            algorithm,
91            params: None,
92        }
93    }
94}
95
96#[cfg(test)]
97mod tests {
98    use super::*;
99
100    #[test]
101    fn algorithm_id_from_u16() {
102        let algorithm = AlgorithmId::from(0);
103        assert_eq!(algorithm, AlgorithmId::Reserved);
104
105        let algorithm = AlgorithmId::from(1);
106        assert_eq!(algorithm, AlgorithmId::MD5);
107
108        let algorithm = AlgorithmId::from(2);
109        assert_eq!(algorithm, AlgorithmId::SHA256);
110
111        let algorithm = AlgorithmId::from(3);
112        assert_eq!(algorithm, AlgorithmId::Unassigned(3));
113    }
114
115    #[test]
116    fn u16_from_algorithm_id() {
117        let val = u16::from(AlgorithmId::Reserved);
118        assert_eq!(val, 0);
119
120        let val = u16::from(AlgorithmId::MD5);
121        assert_eq!(val, 1);
122
123        let val = u16::from(AlgorithmId::SHA256);
124        assert_eq!(val, 2);
125
126        let val = u16::from(AlgorithmId::Unassigned(3));
127        assert_eq!(val, 3);
128    }
129
130    #[test]
131    fn display_algorithm_id() {
132        let out = format!("{}", AlgorithmId::Reserved);
133        assert_eq!("reserved", out);
134
135        let out = format!("{}", AlgorithmId::MD5);
136        assert_eq!("md5", out);
137
138        let out = format!("{}", AlgorithmId::SHA256);
139        assert_eq!("sha256", out);
140
141        let out = format!("{}", AlgorithmId::Unassigned(3));
142        assert_eq!("unassigned(3)", out);
143    }
144
145    #[test]
146    fn algorithm() {
147        let algorithm_1 = Algorithm::from(AlgorithmId::MD5);
148        let algorithm_2 = Algorithm::new(AlgorithmId::MD5, None);
149
150        assert_eq!(algorithm_1, algorithm_2);
151    }
152}