1use std::{num::{ParseFloatError, ParseIntError}, str::Utf8Error};
2
3#[derive(Clone, Copy, Hash, PartialEq)]
4pub struct KeyString {
5 inner: [u8;64],
6}
7
8impl std::fmt::Debug for KeyString {
9 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
10 f.debug_struct("KeyString").field("inner", &self.as_str()).finish()
11 }
12}
13
14impl std::fmt::Display for KeyString {
15 fn fmt(&self, f: &mut std::fmt::Formatter) -> std::fmt::Result {
16 let text = bytes_to_str(&self.inner).expect(&format!("A KeyString should always be valid utf8.\nThe KeyString that was just attempted to Display was:\n{:x?}", self.inner));
17 write!(f, "{}", text)
18 }
19}
20
21impl Default for KeyString {
22 fn default() -> Self {
23 Self { inner: [0;64] }
24 }
25}
26
27impl From<&str> for KeyString {
29 fn from(s: &str) -> Self {
30
31 let mut inner = [0u8;64];
32
33 let mut min = std::cmp::min(s.len(), 64);
34 inner[0..min].copy_from_slice(&s.as_bytes()[0..min]);
35
36 loop {
37 if min == 0 {break}
38 match std::str::from_utf8(&inner[0..min]) {
39 Ok(_) => break,
40 Err(_) => min -= 1,
41 }
42 }
43
44 KeyString {
45 inner
46 }
47
48 }
49}
50
51
52impl TryFrom<&[u8]> for KeyString {
53 type Error = Utf8Error;
54
55 fn try_from(s: &[u8]) -> Result<Self, Self::Error> {
56 let mut inner = [0u8;64];
57
58 let min = std::cmp::min(s.len(), 64);
59 inner[0..min].copy_from_slice(&s[0..min]);
60
61 match std::str::from_utf8(&inner) {
62 Ok(_) => {
63 Ok(KeyString {inner})
64 },
65 Err(e) => Err(e),
66 }
67 }
68}
69
70impl Eq for KeyString {}
71
72impl Ord for KeyString {
73 fn cmp(&self, other: &Self) -> std::cmp::Ordering {
74 self.as_str().cmp(other.as_str())
75 }
76}
77
78impl PartialOrd for KeyString {
79 fn partial_cmp(&self, other: &Self) -> Option<std::cmp::Ordering> {
80 Some(self.as_str().cmp(other.as_str()))
81 }
82}
83
84impl KeyString {
85
86 pub fn new() -> Self {
87 KeyString {
88 inner: [0u8; 64]
89 }
90 }
91
92 pub fn len(&self) -> usize {
93 let mut output = 0;
94 for byte in self.inner {
95 match byte {
96 0 => break,
97 _ => output += 1,
98 }
99 }
100 output
101 }
102
103 pub fn push(&mut self, s: &str) {
104
105 if self.len() + s.len() > 64 {
106 return
107 }
108
109 let mut end_index = 0;
110 for (index, byte) in self.inner.iter().enumerate() {
111 if byte == &0 {
112 end_index = index+1;
113 }
114 }
115
116 for (index, byte) in s.as_bytes().iter().enumerate() {
117 self.inner[index+end_index] = *byte;
118 }
119
120 }
121
122 pub fn as_str(&self) -> &str {
123 unsafe { std::str::from_utf8_unchecked(&self.inner[0..self.len()]) }
125 }
126
127 pub fn as_bytes(&self) -> &[u8] {
128 &self.inner[0..self.len()]
129 }
130
131 pub fn raw(&self) -> &[u8] {
132 &self.inner
133 }
134
135 pub fn to_i32(&self) -> i32 {
137 self.as_str().parse::<i32>().unwrap()
138 }
139
140 pub fn to_f32(&self) -> f32 {
142 self.as_str().parse::<f32>().unwrap()
143 }
144
145 pub fn to_i32_checked(&self) -> Result<i32, ParseIntError> {
146 self.as_str().parse::<i32>()
147 }
148
149 pub fn to_f32_checked(&self) -> Result<f32, ParseFloatError> {
150 self.as_str().parse::<f32>()
151 }
152
153}
154
155
156pub fn bytes_to_str(bytes: &[u8]) -> Result<&str, Utf8Error> {
158 let mut index: usize = 0;
159 let len = bytes.len();
160 let mut start: usize = 0;
161
162 while index < len {
163 if bytes[index] != 0 {
164 break
165 }
166 index += 1;
167 start += 1;
168 }
169
170 if bytes.is_empty() {
171 return Ok("")
172 }
173
174 if start >= bytes.len()-1 {
175 return Ok("")
176 }
177
178 let mut stop: usize = start;
179 while index < len {
180 if bytes[index] == 0 {
181 break
182 }
183 index += 1;
184 stop += 1;
185 }
186
187 std::str::from_utf8(&bytes[start..stop])
188}
189
190
191
192pub fn add(left: usize, right: usize) -> usize {
193 left + right
194}
195
196#[cfg(test)]
197mod tests {
198 use super::*;
199
200 #[test]
201 fn it_works() {
202 let result = add(2, 2);
203 assert_eq!(result, 4);
204 }
205}