1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
use core::{fmt::{Display, Debug}, str::FromStr, ops::Deref};
use encdec::{Encode, Decode};
#[derive(Clone, PartialEq, Encode, Decode)]
pub struct Stringish<const N: usize>(pub(crate) [u8; N]);
impl<const N: usize> FromStr for Stringish<N> {
type Err = ();
fn from_str(s: &str) -> Result<Self, Self::Err> {
let mut d = [0u8; N];
let b = s.as_bytes();
if b.len() > N {
return Err(())
}
d[..b.len()].copy_from_slice(b);
Ok(Self(d))
}
}
impl<const N: usize> From<&str> for Stringish<N> {
fn from(value: &str) -> Self {
let b = value.as_bytes();
let n = b.len().min(N);
let mut d = [0u8; N];
d[..n].copy_from_slice(&b[..n]);
Self(d)
}
}
impl <const N: usize> Default for Stringish<N> {
fn default() -> Self {
Self([0u8; N])
}
}
impl <const N: usize>Display for Stringish<N> {
fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {
write!(f, "{}", self.as_ref())
}
}
impl <const N: usize>Debug for Stringish<N> {
fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {
f.debug_tuple("Stringish").field(&self.as_ref()).finish()
}
}
impl <const N: usize> AsRef<str> for Stringish<N> {
fn as_ref(&self) -> &str {
let n = self.0.iter().enumerate().find_map(|(n, c)| {
if *c == 0 {
return Some(n)
} else {
return None
}
}).unwrap_or(N);
match core::str::from_utf8(&self.0[..n]) {
Ok(v) => v,
Err(_) => "INVALID_U2F8",
}
}
}
impl <const N: usize> Deref for Stringish<N> {
type Target = [u8; N];
fn deref(&self) -> &Self::Target {
&self.0
}
}
#[cfg(test)]
mod test {
use encdec::{Encode, Decode};
use super::Stringish;
#[test]
fn deref() {
let s = Stringish(*b"testing123\0\0\0\0\0\0");
assert_eq!(s.as_ref(), "testing123");
}
#[test]
fn encode_decode() {
let s = Stringish(*b"testing123\0\0\0\0\0\0");
let mut b = [0xffu8; 32];
let n = s.encode(&mut b).unwrap();
assert_eq!(n, 16);
assert_eq!(&b[..16], &s.0[..16]);
assert_eq!(&b[16..], &[0xff; 16]);
let (s1, n1) = Stringish::<16>::decode(&b[..16]).unwrap();
assert_eq!(n1, 16);
assert_eq!(s1, s);
}
}