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