coap_zero/message/
token.rs1use core::hash::Hash;
10
11use super::Error;
12
13#[allow(missing_docs)]
15#[derive(Debug, Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Hash)]
16pub enum TokenLength {
17 Zero = 0,
18 One = 1,
19 Two = 2,
20 Three = 3,
21 Four = 4,
22 Five = 5,
23 Six = 6,
24 Seven = 7,
25 Eight = 8,
26}
27
28impl TryFrom<u8> for TokenLength {
29 type Error = Error;
30
31 fn try_from(value: u8) -> Result<Self, Self::Error> {
32 match value {
33 0 => Ok(TokenLength::Zero),
34 1 => Ok(TokenLength::One),
35 2 => Ok(TokenLength::Two),
36 3 => Ok(TokenLength::Three),
37 4 => Ok(TokenLength::Four),
38 5 => Ok(TokenLength::Five),
39 6 => Ok(TokenLength::Six),
40 7 => Ok(TokenLength::Seven),
41 8 => Ok(TokenLength::Eight),
42 _ => Err(Error::TokenLength),
43 }
44 }
45}
46
47#[allow(clippy::from_over_into)] impl Into<u8> for TokenLength {
49 fn into(self) -> u8 {
50 self as u8
51 }
52}
53
54impl TryFrom<usize> for TokenLength {
55 type Error = Error;
56
57 fn try_from(value: usize) -> Result<Self, Self::Error> {
58 if value > 255 {
59 Err(Error::TokenLength)
60 } else {
61 Self::try_from(value as u8)
62 }
63 }
64}
65
66#[allow(clippy::from_over_into)] impl Into<usize> for TokenLength {
68 fn into(self) -> usize {
69 self as usize
70 }
71}
72
73#[derive(Debug, Clone, Copy)]
78pub struct Token {
79 pub(crate) bytes: [u8; 8],
82 pub(crate) length: TokenLength,
85}
86
87impl Default for Token {
88 fn default() -> Self {
89 Self {
90 bytes: [0_u8; 8],
91 length: TokenLength::Zero,
92 }
93 }
94}
95
96impl Token {
97 pub(crate) fn try_new<RNG: embedded_hal::blocking::rng::Read>(
98 length: TokenLength,
99 rng: &mut RNG,
100 ) -> Result<Self, RNG::Error> {
101 let mut token = Token {
102 length,
103 ..Default::default()
104 };
105
106 rng.read(&mut token.bytes[..token.length as usize])?;
107
108 Ok(token)
109 }
110}
111
112impl TryFrom<&[u8]> for Token {
113 type Error = Error;
114
115 fn try_from(value: &[u8]) -> Result<Self, Self::Error> {
116 let mut token = Token {
117 bytes: [0_u8; 8],
118 length: (value.len() as u8).try_into()?,
119 };
120
121 token.bytes[..token.length.into()].copy_from_slice(value);
122
123 Ok(token)
124 }
125}
126
127impl PartialEq for Token {
128 fn eq(&self, other: &Self) -> bool {
129 self.bytes[..self.length.into()] == other.bytes[..other.length.into()]
130 }
131}
132
133impl Eq for Token {}
134
135impl PartialOrd for Token {
136 fn partial_cmp(&self, other: &Self) -> Option<core::cmp::Ordering> {
137 Some(self.cmp(other))
138 }
139}
140
141impl Ord for Token {
142 fn cmp(&self, other: &Self) -> core::cmp::Ordering {
143 if self.length != other.length {
144 return self.length.cmp(&other.length);
145 }
146 self.bytes[..self.length.into()].cmp(&other.bytes[..self.length.into()])
147 }
148}
149
150impl Hash for Token {
151 fn hash<H: core::hash::Hasher>(&self, state: &mut H) {
152 self.bytes[..self.length.into()].hash(state)
153 }
154}
155
156#[cfg(test)]
157mod tests {
158 use super::*;
159
160 #[test]
161 fn partial_eq() {
162 let a = Token {
163 bytes: [0; 8],
164 length: 8_u8.try_into().unwrap(),
165 };
166 let b = Token {
167 bytes: [1; 8],
168 length: 8_u8.try_into().unwrap(),
169 };
170 let c = Token {
171 bytes: [0; 8],
172 length: 4_u8.try_into().unwrap(),
173 };
174 assert_eq!(a, a); assert_ne!(a, b); assert_ne!(a, c); assert_ne!(b, c); }
179}