1#[cfg(feature = "galloc")]
9use alloc::vec::Vec;
10use core::ops::Deref;
11
12use super::{CHAR_MINUS, DIGITS, SEG_8};
13
14const INT_CONVERT_MAX_SIZE: usize = 11;
15
16#[derive(Debug)]
19pub struct IntConvertResult {
20 offset: usize,
21 bytes: [u8; INT_CONVERT_MAX_SIZE],
22}
23
24impl IntConvertResult {
25 fn new() -> IntConvertResult {
26 IntConvertResult {
27 offset: INT_CONVERT_MAX_SIZE,
28 bytes: [0; INT_CONVERT_MAX_SIZE],
29 }
30 }
31
32 fn last(&self) -> u8 {
33 self.bytes[self.bytes.len() - 1]
34 }
35
36 fn set_last(&mut self, byte: u8) {
37 self.bytes[self.bytes.len() - 1] = byte;
38 }
39
40 fn add_first(&mut self, byte: u8) {
41 if self.offset == 0 {
42 return;
43 }
44
45 self.offset -= 1;
46 self.bytes[self.offset] = byte;
47 }
48
49 fn add_last(&mut self, byte: u8) {
50 if self.offset == 0 {
51 return;
52 }
53
54 self.offset -= 1;
55
56 for i in self.offset..(self.bytes.len() - 1) {
57 self.bytes[i] = self.bytes[i + 1];
58 }
59 self.bytes[self.bytes.len() - 1] = byte;
60 }
61
62 fn remove_last(&mut self) {
63 if self.is_empty() {
64 return;
65 }
66
67 if self.len() > 1 {
68 for i in ((self.offset + 1)..self.bytes.len()).rev() {
69 self.bytes[i] = self.bytes[i - 1];
70 }
71 }
72 self.offset += 1;
73 }
74
75 fn len(&self) -> usize {
76 let len = self.bytes.len() - self.offset;
77 if len > 0 {
78 len
79 } else {
80 0
81 }
82 }
83
84 fn is_empty(&self) -> bool {
85 self.len() == 0
86 }
87}
88
89impl Deref for IntConvertResult {
90 type Target = [u8];
91 fn deref(&self) -> &Self::Target {
92 &self.bytes[self.offset..self.bytes.len()]
93 }
94}
95
96#[derive(Debug)]
99pub struct DoubleConvertResult {
100 offset: usize,
101 bytes: [u8; INT_CONVERT_MAX_SIZE * 2],
102}
103
104impl DoubleConvertResult {
105 fn new(head: &[u8], tail: &[u8]) -> DoubleConvertResult {
106 let mut offset = INT_CONVERT_MAX_SIZE * 2;
107 let mut bytes = [0; INT_CONVERT_MAX_SIZE * 2];
108 let len = head.len() + tail.len();
109 if len <= INT_CONVERT_MAX_SIZE * 2 {
110 offset -= len;
111 let mut idx = offset;
112 for i in 0..head.len() {
113 bytes[idx] = head[i];
114 idx += 1;
115 }
116 for i in 0..tail.len() {
117 bytes[idx] = tail[i];
118 idx += 1;
119 }
120 }
121
122 DoubleConvertResult {
123 offset: offset,
124 bytes: bytes,
125 }
126 }
127}
128
129impl Deref for DoubleConvertResult {
130 type Target = [u8];
131 fn deref(&self) -> &Self::Target {
132 &self.bytes[self.offset..self.bytes.len()]
133 }
134}
135
136pub fn int_to_bytes(value: i32) -> IntConvertResult {
139 let mut result = IntConvertResult::new();
140 let mut v = if value < 0 { value * -1 } else { value };
141 while v > 0 {
142 result.add_first(DIGITS[(v % 10) as usize]);
143 v /= 10;
144 }
145 if value < 0 {
146 result.add_first(CHAR_MINUS);
147 }
148 if result.is_empty() {
149 result.add_first(DIGITS[0]);
150 }
151 result
152}
153
154pub fn float_to_bytes(value: f32) -> DoubleConvertResult {
158 float_to_bytes_ex(value, 10, false)
159}
160
161pub fn float_to_bytes_ex(value: f32, precision: u8, zero_pad: bool) -> DoubleConvertResult {
170 let whole = value as i32;
171 let mut wresult = int_to_bytes(whole);
172
173 let mut fract_part = fractional_part_to_bytes(value, precision);
174 if zero_pad {
175 while fract_part.len() < precision as usize {
176 fract_part.add_last(DIGITS[0]);
177 }
178 }
179
180 let with_dot = wresult.last() | SEG_8;
181 wresult.set_last(with_dot);
182 DoubleConvertResult::new(&wresult, &fract_part)
183}
184
185fn fractional_part_to_bytes(value: f32, precision: u8) -> IntConvertResult {
186 let mut v = if value < 0.0 { value * -1.0 } else { value };
187 let whole = v as i32;
188 v -= whole as f32;
189
190 let mut all_zero = true;
191 let mut zeroes = 0;
192
193 let mut result = IntConvertResult::new();
194 for _ in 0..precision {
195 v *= 10.0;
196 let d = v as i32 % 10;
197 if d == 0 {
198 zeroes += 1;
199 } else {
200 zeroes = 0;
201 all_zero = false;
202 }
203 result.add_last(DIGITS[(d % 10) as usize]);
204 if zeroes >= 4 {
205 for _ in 1..=zeroes {
208 result.remove_last();
209 }
210 break;
211 }
212 }
213 if all_zero {
214 let mut z = IntConvertResult::new();
215 z.add_last(DIGITS[0]);
216 z
217 } else {
218 result
219 }
220}
221
222#[cfg(feature = "galloc")]
227pub fn double_bytes(input: &[u8]) -> Vec<u8> {
228 let mut double_byte = Vec::<u8>::new();
229 for i in 0..input.len() {
230 double_byte.push(input[i]);
231 double_byte.push(0);
232 }
233 double_byte
234}
235
236#[cfg(test)]
237mod tests {
238 use super::*;
239
240 #[test]
241 fn int_to_bytes_output() {
242 assert_eq!(int_to_bytes(0).as_ref(), &[DIGITS[0]]);
243
244 assert_eq!(
245 int_to_bytes(1234567890).as_ref(),
246 &[
247 DIGITS[1], DIGITS[2], DIGITS[3], DIGITS[4], DIGITS[5], DIGITS[6], DIGITS[7],
248 DIGITS[8], DIGITS[9], DIGITS[0]
249 ]
250 );
251
252 assert_eq!(
253 int_to_bytes(-1234567890).as_ref(),
254 &[
255 CHAR_MINUS, DIGITS[1], DIGITS[2], DIGITS[3], DIGITS[4], DIGITS[5], DIGITS[6],
256 DIGITS[7], DIGITS[8], DIGITS[9], DIGITS[0]
257 ]
258 );
259
260 assert_eq!(
261 int_to_bytes(-1234).as_ref(),
262 &[CHAR_MINUS, DIGITS[1], DIGITS[2], DIGITS[3], DIGITS[4]]
263 );
264 }
265
266 #[test]
267 fn float_to_bytes_test() {
268 assert_eq!(float_to_bytes(0.0).deref(), &[DIGITS[0] | SEG_8, DIGITS[0]]);
269
270 assert_eq!(
271 float_to_bytes(-12345.0).deref(),
272 &[
273 CHAR_MINUS,
274 DIGITS[1],
275 DIGITS[2],
276 DIGITS[3],
277 DIGITS[4],
278 DIGITS[5] | SEG_8,
279 DIGITS[0]
280 ]
281 );
282
283 assert_eq!(
284 float_to_bytes(-5.012).deref(),
285 &[
286 CHAR_MINUS,
287 DIGITS[5] | SEG_8,
288 DIGITS[0],
289 DIGITS[1],
290 DIGITS[2]
291 ]
292 );
293 assert_eq!(
294 float_to_bytes(12345.0).deref(),
295 &[
296 DIGITS[1],
297 DIGITS[2],
298 DIGITS[3],
299 DIGITS[4],
300 DIGITS[5] | SEG_8,
301 DIGITS[0]
302 ]
303 );
304
305 assert_eq!(
306 float_to_bytes(-5.20000123).deref(),
307 &[CHAR_MINUS, DIGITS[5] | SEG_8, DIGITS[2]]
308 );
309 }
310
311 #[test]
312 fn float_to_bytes_ex_test() {
313 assert_eq!(
314 float_to_bytes_ex(0.0, 2, true).deref(),
315 &[DIGITS[0] | SEG_8, DIGITS[0], DIGITS[0]]
316 );
317
318 assert_eq!(
319 float_to_bytes_ex(0.123, 2, true).deref(),
320 &[DIGITS[0] | SEG_8, DIGITS[1], DIGITS[2]]
321 );
322
323 assert_eq!(
324 float_to_bytes_ex(0.123, 5, true).deref(),
325 &[
326 DIGITS[0] | SEG_8,
327 DIGITS[1],
328 DIGITS[2],
329 DIGITS[3],
330 DIGITS[0],
331 DIGITS[0]
332 ]
333 );
334 }
335
336 #[test]
337 #[cfg(feature = "galloc")]
338 fn double_bytes_test() {
339 let input: [u8; 4] = [1, 2, 3, 4];
340 let check: [u8; 8] = [1, 0, 2, 0, 3, 0, 4, 0];
341 let result = double_bytes(&input);
342 assert_eq!(check, result.as_slice());
343 }
344}