libdd_trace_utils/msgpack_decoder/decode/
number.rs1use crate::msgpack_decoder::decode::error::DecodeError;
5use rmp::{decode::RmpRead, Marker};
6use std::fmt;
7
8#[derive(Debug, PartialEq)]
9pub enum Number {
10 Unsigned(u64),
11 Signed(i64),
12 Float(f64),
13}
14
15impl fmt::Display for Number {
16 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
17 match self {
18 Number::Signed(val) => write!(f, "{val}"),
19 Number::Unsigned(val) => write!(f, "{val}"),
20 Number::Float(val) => write!(f, "{val}"),
21 }
22 }
23}
24
25impl Number {
26 pub fn bounded_int_conversion<T>(
27 self,
28 lower_bound: T,
29 upper_bound: Option<T>,
30 ) -> Result<T, DecodeError>
31 where
32 T: TryInto<i64> + TryInto<u64> + TryInto<i32> + Copy + fmt::Display,
33 i64: TryInto<T>,
34 u64: TryInto<T>,
35 <T as TryInto<i64>>::Error: fmt::Debug,
36 <T as TryInto<u64>>::Error: fmt::Debug,
37 <i64 as TryInto<T>>::Error: fmt::Debug,
38 <u64 as TryInto<T>>::Error: fmt::Debug,
39 {
40 #[allow(clippy::unwrap_used)]
41 match self {
42 Number::Signed(val) => {
43 let upper_bound_check = if let Some(upper_bound) = upper_bound {
44 val <= upper_bound.try_into().unwrap()
45 } else {
46 true
47 };
48 if val >= lower_bound.try_into().unwrap() && upper_bound_check {
49 val.try_into()
50 .map_err(|e| DecodeError::InvalidConversion(format!("{e:?}")))
51 } else {
52 Err(DecodeError::InvalidConversion(format!(
53 "{val} is out of bounds for conversion"
54 )))
55 }
56 }
57 Number::Unsigned(val) => {
58 let upper_bound_check = if let Some(upper_bound) = upper_bound {
59 val <= upper_bound.try_into().unwrap()
60 } else {
61 true
62 };
63
64 if upper_bound_check {
65 val.try_into()
66 .map_err(|e| DecodeError::InvalidConversion(format!("{e:?}")))
67 } else {
68 Err(DecodeError::InvalidConversion(format!(
69 "{val} is out of bounds for conversion"
70 )))
71 }
72 }
73 _ => Err(DecodeError::InvalidConversion(
74 "Cannot convert float to int".to_owned(),
75 )),
76 }
77 }
78}
79
80impl TryFrom<Number> for i8 {
81 type Error = DecodeError;
82 fn try_from(value: Number) -> Result<Self, Self::Error> {
83 value.bounded_int_conversion(i8::MIN, Some(i8::MAX))
84 }
85}
86
87impl TryFrom<Number> for i32 {
88 type Error = DecodeError;
89 fn try_from(value: Number) -> Result<Self, Self::Error> {
90 value.bounded_int_conversion(i32::MIN, Some(i32::MAX))
91 }
92}
93
94impl TryFrom<Number> for i64 {
95 type Error = DecodeError;
96 fn try_from(value: Number) -> Result<Self, Self::Error> {
97 value.bounded_int_conversion(i64::MIN, Some(i64::MAX))
98 }
99}
100
101impl TryFrom<Number> for u8 {
102 type Error = DecodeError;
103 fn try_from(value: Number) -> Result<Self, Self::Error> {
104 value.bounded_int_conversion(u8::MIN, Some(u8::MAX))
105 }
106}
107
108impl TryFrom<Number> for u32 {
109 type Error = DecodeError;
110 fn try_from(value: Number) -> Result<Self, Self::Error> {
111 value.bounded_int_conversion(u32::MIN, Some(u32::MAX))
112 }
113}
114
115impl TryFrom<Number> for u64 {
116 type Error = DecodeError;
117 fn try_from(value: Number) -> Result<Self, Self::Error> {
118 value.bounded_int_conversion(u64::MIN, None)
119 }
120}
121
122impl TryFrom<Number> for f64 {
123 type Error = DecodeError;
124 fn try_from(value: Number) -> Result<Self, Self::Error> {
125 match value {
126 Number::Unsigned(val) => {
127 if val <= f64::MAX as u64 {
128 Ok(val as f64)
129 } else {
130 Err(DecodeError::InvalidConversion(format!(
131 "{val} is out of bounds for conversion"
132 )))
133 }
134 }
135 Number::Signed(val) => {
136 if val >= f64::MIN as i64 && val <= f64::MAX as i64 {
137 Ok(val as f64)
138 } else {
139 Err(DecodeError::InvalidConversion(format!(
140 "{val} is out of bounds for conversion"
141 )))
142 }
143 }
144 Number::Float(val) => Ok(val),
145 }
146 }
147}
148
149fn read_number(buf: &mut &[u8], allow_null: bool) -> Result<Number, DecodeError> {
150 match rmp::decode::read_marker(buf)
151 .map_err(|_| DecodeError::InvalidFormat("Unable to read marker for number".to_owned()))?
152 {
153 Marker::FixPos(val) => Ok(Number::Unsigned(val as u64)),
154 Marker::FixNeg(val) => Ok(Number::Signed(val as i64)),
155 Marker::U8 => Ok(Number::Unsigned(
156 buf.read_data_u8().map_err(|_| DecodeError::IOError)? as u64,
157 )),
158 Marker::U16 => Ok(Number::Unsigned(
159 buf.read_data_u16().map_err(|_| DecodeError::IOError)? as u64,
160 )),
161 Marker::U32 => Ok(Number::Unsigned(
162 buf.read_data_u32().map_err(|_| DecodeError::IOError)? as u64,
163 )),
164 Marker::U64 => Ok(Number::Unsigned(
165 buf.read_data_u64().map_err(|_| DecodeError::IOError)?,
166 )),
167 Marker::I8 => Ok(Number::Signed(
168 buf.read_data_i8().map_err(|_| DecodeError::IOError)? as i64,
169 )),
170 Marker::I16 => Ok(Number::Signed(
171 buf.read_data_i16().map_err(|_| DecodeError::IOError)? as i64,
172 )),
173 Marker::I32 => Ok(Number::Signed(
174 buf.read_data_i32().map_err(|_| DecodeError::IOError)? as i64,
175 )),
176 Marker::I64 => Ok(Number::Signed(
177 buf.read_data_i64().map_err(|_| DecodeError::IOError)?,
178 )),
179 Marker::F32 => Ok(Number::Float(
180 buf.read_data_f32().map_err(|_| DecodeError::IOError)? as f64,
181 )),
182 Marker::F64 => Ok(Number::Float(
183 buf.read_data_f64().map_err(|_| DecodeError::IOError)?,
184 )),
185 Marker::Null => {
186 if allow_null {
187 Ok(Number::Unsigned(0))
188 } else {
189 Err(DecodeError::InvalidType("Invalid number type".to_owned()))
190 }
191 }
192 _ => Err(DecodeError::InvalidType("Invalid number type".to_owned())),
193 }
194}
195
196pub fn read_number_slice<T: TryFrom<Number, Error = DecodeError>>(
198 buf: &mut &[u8],
199) -> Result<T, DecodeError> {
200 read_number(buf, false)?.try_into()
201}
202
203pub fn read_nullable_number_slice<T: TryFrom<Number, Error = DecodeError>>(
205 buf: &mut &[u8],
206) -> Result<T, DecodeError> {
207 read_number(buf, true)?.try_into()
208}
209
210#[cfg(test)]
211mod tests {
212 use super::*;
213 use serde_json::json;
214 use std::f64;
215
216 #[test]
217 fn test_decoding_not_nullable_slice_to_unsigned() {
218 let mut buf = Vec::new();
219 let expected_value = 42;
220 let val = json!(expected_value);
221 rmp_serde::encode::write_named(&mut buf, &val).unwrap();
222 let mut slice = buf.as_slice();
223 let result: u8 = read_number_slice(&mut slice).unwrap();
224 assert_eq!(result, expected_value);
225 }
226
227 #[test]
228 fn test_decoding_not_nullable_slice_to_signed() {
229 let mut buf = Vec::new();
230 let expected_value = 42;
231 let val = json!(expected_value);
232 rmp_serde::encode::write_named(&mut buf, &val).unwrap();
233 let mut slice = buf.as_slice();
234 let result: i8 = read_number_slice(&mut slice).unwrap();
235 assert_eq!(result, expected_value);
236 }
237
238 #[test]
239 fn test_decoding_not_nullable_slice_to_float() {
240 let mut buf = Vec::new();
241 let expected_value = 42.98;
242 let val = json!(expected_value);
243 rmp_serde::encode::write_named(&mut buf, &val).unwrap();
244 let mut slice = buf.as_slice();
245 let result: f64 = read_number_slice(&mut slice).unwrap();
246 assert_eq!(result, expected_value);
247 }
248
249 #[test]
250 fn test_decoding_null_through_read_number_slice_raises_exception() {
251 let mut buf = Vec::new();
252 let val = json!(null);
253 rmp_serde::encode::write_named(&mut buf, &val).unwrap();
254 let mut slice = buf.as_slice();
255 let result: Result<u8, DecodeError> = read_number_slice(&mut slice);
256 assert!(matches!(result, Err(DecodeError::InvalidType(_))));
257
258 assert_eq!(
259 result.unwrap_err().to_string(),
260 "Invalid type encountered: Invalid number type".to_owned()
261 );
262 }
263
264 #[test]
265 fn test_decoding_null_slice_to_unsigned() {
266 let mut buf = Vec::new();
267 let val = json!(null);
268 rmp_serde::encode::write_named(&mut buf, &val).unwrap();
269 let mut slice = buf.as_slice();
270 let result: u8 = read_nullable_number_slice(&mut slice).unwrap();
271 assert_eq!(result, 0);
272 }
273
274 #[test]
275 fn test_decoding_null_slice_to_signed() {
276 let mut buf = Vec::new();
277 let val = json!(null);
278 rmp_serde::encode::write_named(&mut buf, &val).unwrap();
279 let mut slice = buf.as_slice();
280 let result: i8 = read_nullable_number_slice(&mut slice).unwrap();
281 assert_eq!(result, 0);
282 }
283
284 #[test]
285 fn test_decoding_null_slice_to_float() {
286 let mut buf = Vec::new();
287 let val = json!(null);
288 rmp_serde::encode::write_named(&mut buf, &val).unwrap();
289 let mut slice = buf.as_slice();
290 let result: f64 = read_nullable_number_slice(&mut slice).unwrap();
291 assert_eq!(result, 0.0);
292 }
293
294 #[test]
295 fn test_i64_conversions() {
296 let valid_max = i64::MAX;
297 let valid_unsigned_number = Number::Unsigned(valid_max as u64);
298 let zero_unsigned = Number::Unsigned(0u64);
299 let zero_signed = Number::Signed(0);
300 let valid_signed_number = Number::Signed(valid_max);
301 let invalid_float_number = Number::Float(4.14);
302 let invalid_unsigned = u64::MAX;
303 let invalid_unsigned_number = Number::Unsigned(invalid_unsigned);
304
305 assert_eq!(
306 valid_max,
307 TryInto::<i64>::try_into(valid_unsigned_number).unwrap()
308 );
309 assert_eq!(
310 valid_max,
311 TryInto::<i64>::try_into(valid_signed_number).unwrap()
312 );
313 assert_eq!(0, TryInto::<i64>::try_into(zero_signed).unwrap());
314 assert_eq!(0, TryInto::<i64>::try_into(zero_unsigned).unwrap());
315 assert_eq!(
316 Err(DecodeError::InvalidConversion(
317 "Cannot convert float to int".to_owned()
318 )),
319 TryInto::<i64>::try_into(invalid_float_number)
320 );
321 assert_eq!(
322 Err(DecodeError::InvalidConversion(format!(
323 "{invalid_unsigned} is out of bounds for conversion"
324 ))),
325 TryInto::<i64>::try_into(invalid_unsigned_number)
326 );
327 }
328 #[test]
329 fn test_i32_conversions() {
330 let valid_signed_upper = i32::MAX;
331 let valid_unsigned_number = Number::Unsigned(valid_signed_upper as u64);
332 let zero_unsigned = Number::Unsigned(0u64);
333 let zero_signed = Number::Signed(0);
334 let valid_signed_number_upper = Number::Signed(valid_signed_upper as i64);
335 let valid_signed_lower = i32::MIN;
336 let valid_signed_number_lower = Number::Signed(valid_signed_lower as i64);
337 let invalid_float_number = Number::Float(4.14);
338 let invalid_unsigned = u64::MAX;
339 let invalid_unsigned_number = Number::Unsigned(invalid_unsigned);
340 let invalid_signed_upper = i32::MAX as i64 + 1;
341 let invalid_signed_number_upper = Number::Signed(invalid_signed_upper);
342 let invalid_signed_lower = i32::MIN as i64 - 1;
343 let invalid_signed_number_lower = Number::Signed(invalid_signed_lower);
344
345 assert_eq!(
346 valid_signed_upper,
347 TryInto::<i32>::try_into(valid_unsigned_number).unwrap()
348 );
349 assert_eq!(
350 valid_signed_upper,
351 TryInto::<i32>::try_into(valid_signed_number_upper).unwrap()
352 );
353 assert_eq!(
354 valid_signed_lower,
355 TryInto::<i32>::try_into(valid_signed_number_lower).unwrap()
356 );
357 assert_eq!(0, TryInto::<i32>::try_into(zero_signed).unwrap());
358 assert_eq!(0, TryInto::<i32>::try_into(zero_unsigned).unwrap());
359 assert_eq!(
360 Err(DecodeError::InvalidConversion(
361 "Cannot convert float to int".to_owned()
362 )),
363 TryInto::<i32>::try_into(invalid_float_number)
364 );
365 assert_eq!(
366 Err(DecodeError::InvalidConversion(format!(
367 "{invalid_unsigned} is out of bounds for conversion"
368 ))),
369 TryInto::<i32>::try_into(invalid_unsigned_number)
370 );
371 assert_eq!(
372 Err(DecodeError::InvalidConversion(format!(
373 "{invalid_signed_upper} is out of bounds for conversion"
374 ))),
375 TryInto::<i32>::try_into(invalid_signed_number_upper)
376 );
377 assert_eq!(
378 Err(DecodeError::InvalidConversion(format!(
379 "{invalid_signed_lower} is out of bounds for conversion"
380 ))),
381 TryInto::<i32>::try_into(invalid_signed_number_lower)
382 );
383 }
384
385 #[test]
386 fn test_i8_null_conversions() {
387 let valid_signed_upper = i8::MAX;
388 let valid_unsigned_number = Number::Unsigned(valid_signed_upper as u64);
389 let zero_unsigned = Number::Unsigned(0u64);
390 let zero_signed = Number::Signed(0);
391 let valid_signed_number_upper = Number::Signed(valid_signed_upper as i64);
392 let valid_signed_lower = i8::MIN;
393 let valid_signed_number_lower = Number::Signed(valid_signed_lower as i64);
394 let invalid_float_number = Number::Float(4.14);
395 let invalid_unsigned = u8::MAX;
396 let invalid_unsigned_number = Number::Unsigned(invalid_unsigned as u64);
397 let invalid_signed_upper = i8::MAX as i64 + 1;
398 let invalid_signed_number_upper = Number::Signed(invalid_signed_upper);
399 let invalid_signed_lower = i8::MIN as i64 - 1;
400 let invalid_signed_number_lower = Number::Signed(invalid_signed_lower);
401
402 assert_eq!(
403 valid_signed_upper,
404 TryInto::<i8>::try_into(valid_unsigned_number).unwrap()
405 );
406 assert_eq!(
407 valid_signed_upper,
408 TryInto::<i8>::try_into(valid_signed_number_upper).unwrap()
409 );
410 assert_eq!(
411 valid_signed_lower,
412 TryInto::<i8>::try_into(valid_signed_number_lower).unwrap()
413 );
414 assert_eq!(0, TryInto::<i8>::try_into(zero_signed).unwrap());
415 assert_eq!(0, TryInto::<i8>::try_into(zero_unsigned).unwrap());
416 assert_eq!(
417 Err(DecodeError::InvalidConversion(
418 "Cannot convert float to int".to_owned()
419 )),
420 TryInto::<i8>::try_into(invalid_float_number)
421 );
422 assert_eq!(
423 Err(DecodeError::InvalidConversion(format!(
424 "{invalid_unsigned} is out of bounds for conversion"
425 ))),
426 TryInto::<i8>::try_into(invalid_unsigned_number)
427 );
428 assert_eq!(
429 Err(DecodeError::InvalidConversion(format!(
430 "{invalid_signed_upper} is out of bounds for conversion"
431 ))),
432 TryInto::<i8>::try_into(invalid_signed_number_upper)
433 );
434 assert_eq!(
435 Err(DecodeError::InvalidConversion(format!(
436 "{invalid_signed_lower} is out of bounds for conversion"
437 ))),
438 TryInto::<i8>::try_into(invalid_signed_number_lower)
439 );
440 }
441
442 #[test]
443 fn test_i8_conversions() {
444 let valid_signed_upper = i8::MAX;
445 let valid_unsigned_number = Number::Unsigned(valid_signed_upper as u64);
446 let zero_unsigned = Number::Unsigned(0u64);
447 let zero_signed = Number::Signed(0);
448 let valid_signed_number_upper = Number::Signed(valid_signed_upper as i64);
449 let valid_signed_lower = i8::MIN;
450 let valid_signed_number_lower = Number::Signed(valid_signed_lower as i64);
451 let invalid_float_number = Number::Float(4.14);
452 let invalid_unsigned = u8::MAX;
453 let invalid_unsigned_number = Number::Unsigned(invalid_unsigned as u64);
454 let invalid_signed_upper = i8::MAX as i64 + 1;
455 let invalid_signed_number_upper = Number::Signed(invalid_signed_upper);
456 let invalid_signed_lower = i8::MIN as i64 - 1;
457 let invalid_signed_number_lower = Number::Signed(invalid_signed_lower);
458
459 assert_eq!(
460 valid_signed_upper,
461 TryInto::<i8>::try_into(valid_unsigned_number).unwrap()
462 );
463 assert_eq!(
464 valid_signed_upper,
465 TryInto::<i8>::try_into(valid_signed_number_upper).unwrap()
466 );
467 assert_eq!(
468 valid_signed_lower,
469 TryInto::<i8>::try_into(valid_signed_number_lower).unwrap()
470 );
471 assert_eq!(0, TryInto::<i8>::try_into(zero_signed).unwrap());
472 assert_eq!(0, TryInto::<i8>::try_into(zero_unsigned).unwrap());
473 assert_eq!(
474 Err(DecodeError::InvalidConversion(
475 "Cannot convert float to int".to_owned()
476 )),
477 TryInto::<i8>::try_into(invalid_float_number)
478 );
479 assert_eq!(
480 Err(DecodeError::InvalidConversion(format!(
481 "{invalid_unsigned} is out of bounds for conversion"
482 ))),
483 TryInto::<i8>::try_into(invalid_unsigned_number)
484 );
485 assert_eq!(
486 Err(DecodeError::InvalidConversion(format!(
487 "{invalid_signed_upper} is out of bounds for conversion"
488 ))),
489 TryInto::<i8>::try_into(invalid_signed_number_upper)
490 );
491 assert_eq!(
492 Err(DecodeError::InvalidConversion(format!(
493 "{invalid_signed_lower} is out of bounds for conversion"
494 ))),
495 TryInto::<i8>::try_into(invalid_signed_number_lower)
496 );
497 }
498
499 #[test]
500 fn test_u8_conversions() {
501 let valid_signed_upper = u8::MAX;
502 let valid_unsigned_number = Number::Unsigned(valid_signed_upper as u64);
503 let zero_unsigned = Number::Unsigned(0u64);
504 let zero_signed = Number::Signed(0);
505 let valid_signed_number_upper = Number::Signed(valid_signed_upper as i64);
506 let valid_signed_lower = u8::MIN;
507 let valid_signed_number_lower = Number::Signed(valid_signed_lower as i64);
508 let invalid_float_number = Number::Float(4.14);
509 let invalid_unsigned = (u8::MAX as u64) + 1;
510 let invalid_unsigned_number = Number::Unsigned(invalid_unsigned);
511 let invalid_signed_upper = i32::MAX as i64 + 1;
512 let invalid_signed_number_upper = Number::Signed(invalid_signed_upper);
513 let invalid_signed_lower = i8::MIN as i64;
514 let invalid_signed_number_lower = Number::Signed(invalid_signed_lower);
515
516 assert_eq!(
517 valid_signed_upper,
518 TryInto::<u8>::try_into(valid_unsigned_number).unwrap()
519 );
520 assert_eq!(
521 valid_signed_upper,
522 TryInto::<u8>::try_into(valid_signed_number_upper).unwrap()
523 );
524 assert_eq!(
525 valid_signed_lower,
526 TryInto::<u8>::try_into(valid_signed_number_lower).unwrap()
527 );
528 assert_eq!(0, TryInto::<u8>::try_into(zero_signed).unwrap());
529 assert_eq!(0, TryInto::<u8>::try_into(zero_unsigned).unwrap());
530 assert_eq!(
531 Err(DecodeError::InvalidConversion(
532 "Cannot convert float to int".to_owned()
533 )),
534 TryInto::<u8>::try_into(invalid_float_number)
535 );
536 assert_eq!(
537 Err(DecodeError::InvalidConversion(format!(
538 "{invalid_unsigned} is out of bounds for conversion"
539 ))),
540 TryInto::<u8>::try_into(invalid_unsigned_number)
541 );
542 assert_eq!(
543 Err(DecodeError::InvalidConversion(format!(
544 "{invalid_signed_upper} is out of bounds for conversion"
545 ))),
546 TryInto::<u8>::try_into(invalid_signed_number_upper)
547 );
548 assert_eq!(
549 Err(DecodeError::InvalidConversion(format!(
550 "{invalid_signed_lower} is out of bounds for conversion"
551 ))),
552 TryInto::<u8>::try_into(invalid_signed_number_lower)
553 );
554 }
555
556 #[test]
557 fn test_u32_conversions() {
558 let valid_signed_upper = u32::MAX;
559 let valid_unsigned_number = Number::Unsigned(valid_signed_upper as u64);
560 let zero_unsigned = Number::Unsigned(0u64);
561 let zero_signed = Number::Signed(0);
562 let valid_signed_number_upper = Number::Signed(valid_signed_upper as i64);
563 let valid_signed_lower = u32::MIN;
564 let valid_signed_number_lower = Number::Signed(valid_signed_lower as i64);
565 let invalid_float_number = Number::Float(4.14);
566 let invalid_unsigned = (u32::MAX as u64) + 1;
567 let invalid_unsigned_number = Number::Unsigned(invalid_unsigned);
568 let invalid_signed_upper = i64::MAX;
569 let invalid_signed_number_upper = Number::Signed(invalid_signed_upper);
570 let invalid_signed_lower = i8::MIN as i64;
571 let invalid_signed_number_lower = Number::Signed(invalid_signed_lower);
572
573 assert_eq!(
574 valid_signed_upper,
575 TryInto::<u32>::try_into(valid_unsigned_number).unwrap()
576 );
577 assert_eq!(
578 valid_signed_upper,
579 TryInto::<u32>::try_into(valid_signed_number_upper).unwrap()
580 );
581 assert_eq!(
582 valid_signed_lower,
583 TryInto::<u32>::try_into(valid_signed_number_lower).unwrap()
584 );
585 assert_eq!(0, TryInto::<u32>::try_into(zero_signed).unwrap());
586 assert_eq!(0, TryInto::<u32>::try_into(zero_unsigned).unwrap());
587 assert_eq!(
588 Err(DecodeError::InvalidConversion(
589 "Cannot convert float to int".to_owned()
590 )),
591 TryInto::<u32>::try_into(invalid_float_number)
592 );
593 assert_eq!(
594 Err(DecodeError::InvalidConversion(format!(
595 "{invalid_unsigned} is out of bounds for conversion"
596 ))),
597 TryInto::<u32>::try_into(invalid_unsigned_number)
598 );
599 assert_eq!(
600 Err(DecodeError::InvalidConversion(format!(
601 "{invalid_signed_upper} is out of bounds for conversion"
602 ))),
603 TryInto::<u32>::try_into(invalid_signed_number_upper)
604 );
605 assert_eq!(
606 Err(DecodeError::InvalidConversion(format!(
607 "{invalid_signed_lower} is out of bounds for conversion"
608 ))),
609 TryInto::<u32>::try_into(invalid_signed_number_lower)
610 );
611 }
612
613 #[test]
614 fn test_u64_conversions() {
615 let valid_unsigned = u64::MAX;
616 let valid_unsigned_number = Number::Unsigned(valid_unsigned);
617 let zero_unsigned = Number::Unsigned(0u64);
618 let zero_signed = Number::Signed(0);
619 let valid_signed_upper = i64::MAX as u64;
620 let valid_signed_number_upper = Number::Signed(valid_signed_upper as i64);
621 let valid_signed_lower = u32::MIN as u64;
622 let valid_signed_number_lower = Number::Signed(valid_signed_lower as i64);
623 let invalid_float_number = Number::Float(4.14);
624 let invalid_signed_lower = i8::MIN as i64;
625 let invalid_signed_number_lower = Number::Signed(invalid_signed_lower);
626
627 assert_eq!(
628 valid_unsigned,
629 TryInto::<u64>::try_into(valid_unsigned_number).unwrap()
630 );
631 assert_eq!(
632 valid_signed_upper,
633 TryInto::<u64>::try_into(valid_signed_number_upper).unwrap()
634 );
635 assert_eq!(
636 valid_signed_lower,
637 TryInto::<u64>::try_into(valid_signed_number_lower).unwrap()
638 );
639 assert_eq!(0, TryInto::<u64>::try_into(zero_signed).unwrap());
640 assert_eq!(0, TryInto::<u64>::try_into(zero_unsigned).unwrap());
641 assert_eq!(
642 Err(DecodeError::InvalidConversion(
643 "Cannot convert float to int".to_owned()
644 )),
645 TryInto::<u64>::try_into(invalid_float_number)
646 );
647 assert_eq!(
648 Err(DecodeError::InvalidConversion(format!(
649 "{invalid_signed_lower} is out of bounds for conversion"
650 ))),
651 TryInto::<u64>::try_into(invalid_signed_number_lower)
652 );
653 }
654
655 #[test]
656 fn test_f64_conversions() {
657 let valid_signed_upper = i64::MAX;
658 let valid_unsigned_upper = u64::MAX;
659 let valid_signed_number_upper = Number::Signed(valid_signed_upper);
660 let valid_signed_lower = i64::MIN;
661 let valid_signed_number_lower = Number::Signed(valid_signed_lower);
662 let valid_unsigned_number = Number::Unsigned(valid_unsigned_upper);
663 let zero_unsigned = Number::Unsigned(0u64);
664 let zero_signed = Number::Signed(0);
665 let invalid_unsigned = u64::MAX;
666 let invalid_unsigned_number = Number::Unsigned(invalid_unsigned);
667
668 assert_eq!(
669 valid_unsigned_upper as f64,
670 TryInto::<f64>::try_into(valid_unsigned_number).unwrap()
671 );
672 assert_eq!(
673 valid_signed_upper as f64,
674 TryInto::<f64>::try_into(valid_signed_number_upper).unwrap()
675 );
676 assert_eq!(
677 valid_signed_lower as f64,
678 TryInto::<f64>::try_into(valid_signed_number_lower).unwrap()
679 );
680 assert_eq!(0f64, TryInto::<f64>::try_into(zero_signed).unwrap());
681 assert_eq!(0f64, TryInto::<f64>::try_into(zero_unsigned).unwrap());
682 assert_eq!(
683 Err(DecodeError::InvalidConversion(format!(
684 "{invalid_unsigned} is out of bounds for conversion"
685 ))),
686 TryInto::<i64>::try_into(invalid_unsigned_number)
687 );
688 }
689}