1use std::fmt;
5use std::result::Result;
6use std::str::{from_utf8, FromStr, Utf8Error};
7use crate::error::Error;
8
9#[derive(Clone, Copy, PartialEq, Eq, Hash)]
12pub struct Label([u8; 16]);
13
14impl Label {
15 pub fn as_str(&self) -> Result<&str, Utf8Error> {
17 for i in 0..self.0.len() {
18 if self.0[i] == 0 {
21 return from_utf8(&self.0[0..i])
22 }
23 }
24 return from_utf8(&self.0);
25 }
26
27 pub fn from_bytes(bytes: &[u8]) -> Result<Self, Error> {
33 if bytes.len() > 16 {
34 return Err(Error::TooLongLabel(bytes.len()));
35 }
36
37 let mut storage: [u8; 16] = Default::default();
38 let range = 0..bytes.len();
39 storage[range.clone()].copy_from_slice(&bytes[range]);
40 Ok(storage.into())
41 }
42}
43
44impl fmt::Debug for Label {
45 fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
46 if let Ok(value) = self.as_str() {
47 return write!(f, "Label({})", value);
48 }
49 write!(f, "Label(")?;
50 self.0.fmt(f)?;
51 return write!(f, ")");
52 }
53}
54
55impl fmt::Display for Label {
56 fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
57 let value = self.as_str().map_err(|_| fmt::Error)?;
58 write!(f, "{}", value)
59 }
60}
61
62impl From<[u8; 16]> for Label {
63 fn from(arr: [u8; 16]) -> Self { Label(arr) }
64}
65
66impl AsRef<[u8]> for Label {
67 fn as_ref(&self) -> &[u8] { &self.0 }
68}
69
70impl FromStr for Label {
71 type Err = Error;
72
73 #[inline]
74 fn from_str(value: &str) -> Result<Self, Error> {
75 Self::from_bytes(value.as_bytes())
76 }
77}
78
79#[cfg(test)]
80mod tests {
81 use super::Label;
82
83 #[test]
84 fn label_constructs_from_str() {
85 assert_eq!(Label::from(*b"short\0\0\0\0\0\0\0\0\0\0\0"), "short".parse().unwrap());
86 assert_eq!(Label::from(*b"exact_16_chars_\0"), "exact_16_chars_".parse().unwrap());
87 assert!("more_then_16_char".parse::<Label>().is_err());
88 }
89}