async_coap/message/
token.rs

1// Copyright 2019 Google LLC
2//
3// Licensed under the Apache License, Version 2.0 (the "License");
4// you may not use this file except in compliance with the License.
5// You may obtain a copy of the License at
6//
7//     https://www.apache.org/licenses/LICENSE-2.0
8//
9// Unless required by applicable law or agreed to in writing, software
10// distributed under the License is distributed on an "AS IS" BASIS,
11// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12// See the License for the specific language governing permissions and
13// limitations under the License.
14//
15
16use super::util::encode_u32;
17use core::convert::From;
18use core::ops::Deref;
19
20/// Type for holding the value of a CoAP message token.
21#[derive(Debug, Eq, PartialEq, Hash, Copy, Clone, Ord, PartialOrd)]
22pub struct MsgToken {
23    len: u8,
24    bytes: [u8; 8],
25}
26
27impl MsgToken {
28    /// Constant representing an empty token.
29    pub const EMPTY: MsgToken = MsgToken {
30        len: 0u8,
31        bytes: [0; 8],
32    };
33
34    /// Creates a new token from the given byte slice.
35    pub fn new(x: &[u8]) -> MsgToken {
36        MsgToken::from(x)
37    }
38
39    /// Returns the length of this token.
40    pub fn len(&self) -> usize {
41        self.len as usize
42    }
43
44    /// Returns true if the length of this token is zero.
45    pub fn is_empty(&self) -> bool {
46        self.len == 0
47    }
48
49    /// Returns a byte slice containing this token.
50    pub fn as_bytes(&self) -> &[u8] {
51        &self.bytes[..self.len as usize]
52    }
53}
54
55impl std::fmt::Display for MsgToken {
56    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
57        for b in self.as_bytes() {
58            write!(f, "{:02X}", b)?;
59        }
60        Ok(())
61    }
62}
63
64impl Default for MsgToken {
65    fn default() -> Self {
66        MsgToken::EMPTY
67    }
68}
69
70impl Deref for MsgToken {
71    type Target = [u8];
72
73    fn deref(&self) -> &Self::Target {
74        self.as_bytes()
75    }
76}
77
78impl core::cmp::PartialEq<[u8]> for MsgToken {
79    fn eq(&self, other: &[u8]) -> bool {
80        self.as_bytes() == other
81    }
82}
83
84impl core::convert::From<u32> for MsgToken {
85    fn from(x: u32) -> Self {
86        let mut bytes = [0u8; 8];
87        let len = encode_u32(x, &mut bytes).len();
88        MsgToken {
89            len: len as u8,
90            bytes,
91        }
92    }
93}
94
95impl core::convert::From<i32> for MsgToken {
96    fn from(x: i32) -> Self {
97        core::convert::Into::into(x as u32)
98    }
99}
100
101impl core::convert::From<u16> for MsgToken {
102    fn from(x: u16) -> Self {
103        core::convert::Into::into(x as u32)
104    }
105}
106
107impl core::convert::From<&[u8]> for MsgToken {
108    // Note: this will panic if x is too big.
109    fn from(x: &[u8]) -> Self {
110        let mut bytes = [0u8; 8];
111        let len = x.len();
112        bytes[..len].copy_from_slice(x);
113        MsgToken {
114            len: len as u8,
115            bytes,
116        }
117    }
118}