1use crate::TypeFlag;
2
3#[derive(Debug, Clone, Copy)]
4pub struct Value {
5 pub ty: TypeFlag,
6 pub data: u64,
7}
8
9impl Value {
10 pub fn to_code(self) -> Vec<u8> {
11 self.data.to_le_bytes()[..self.ty.size()].to_vec()
13 }
14
15 pub fn from_code(ty: TypeFlag, code: &[u8]) -> Self {
16 let mut data = [0; 8];
17 if code.len() != ty.size() {
18 panic!("{:?} expects {} bytes, got {}", ty, ty.size(), code.len());
19 }else if code.len() != 8 {
20 let mut idx = 0;
21 for byte in code {
22 data[idx] = *byte;
23 idx += 1;
24 }
25 }else{
26 data.copy_from_slice(code);
27 }
28 Self {
29 ty,
30 data: u64::from_le_bytes(data),
31 }
32 }
33
34 pub fn to_stack(self) -> u64 {
35 self.data
36 }
37
38 pub fn from_stack(ty: TypeFlag, raw: u64) -> Self {
39 Self { ty, data: raw }
40 }
41
42 pub fn to_string(self) -> String {
43 self.into()
44 }
45}
46
47macro_rules! impl_from_value {
48 ($from_type:ty, $type_flag:ident) => {
49 impl From<$from_type> for Value {
50 fn from(value: $from_type) -> Self {
51 Self {
52 ty: TypeFlag::$type_flag,
53 data: value as u64,
54 }
55 }
56 }
57 };
58}
59
60
61
62impl_from_value!(i8, I8);
63impl_from_value!(i16, I16);
64impl_from_value!(i32, I32);
65impl_from_value!(i64, I64);
66
67impl_from_value!(char, Char);
68impl_from_value!(bool, Bool);
69
70impl_from_value!(u8, U8);
71impl_from_value!(u16, U16);
72impl_from_value!(u32, U32);
73impl_from_value!(u64, U64);
74
75
76
77impl From<f32> for Value {
78 fn from(value: f32) -> Self {
79 Self {
80 ty: TypeFlag::F32,
81 data: value.to_bits() as u64,
82 }
83 }
84}
85
86impl From<f64> for Value {
87 fn from(value: f64) -> Self {
88 Self {
89 ty: TypeFlag::F64,
90 data: value.to_bits(),
91 }
92 }
93}
94
95macro_rules! impl_try_into_value {
96 ($to_type:ty, $type_flag:ident) => {
97 impl TryInto<$to_type> for Value {
98 type Error = &'static str;
99
100 fn try_into(self) -> Result<$to_type, Self::Error> {
101 if self.ty == TypeFlag::$type_flag {
102 Ok(self.data as $to_type)
103 } else {
104 Err("invalid type")
105 }
106 }
107 }
108
109 impl TryInto<$to_type> for &Value {
110 type Error = &'static str;
111
112 fn try_into(self) -> Result<$to_type, Self::Error> {
113 if self.ty == TypeFlag::$type_flag {
114 Ok(self.data as $to_type)
115 } else {
116 Err("invalid type")
117 }
118 }
119 }
120 };
121}
122
123impl_try_into_value!(i8, I8);
124impl_try_into_value!(i16, I16);
125impl_try_into_value!(i32, I32);
126impl_try_into_value!(i64, I64);
127
128impl TryInto<char> for Value {
129 type Error = &'static str;
130
131 fn try_into(self) -> Result<char, Self::Error> {
132 if self.ty == TypeFlag::Char {
133 Ok(char::from_u32(self.data as u32).unwrap())
134 } else {
135 Err("invalid type")
136 }
137 }
138}
139
140impl TryInto<char> for &Value {
141 type Error = &'static str;
142
143 fn try_into(self) -> Result<char, Self::Error> {
144 if self.ty == TypeFlag::Char {
145 Ok(char::from_u32(self.data as u32).unwrap())
146 } else {
147 Err("invalid type")
148 }
149 }
150}
151
152impl TryInto<bool> for Value {
153 type Error = &'static str;
154
155 fn try_into(self) -> Result<bool, Self::Error> {
156 if self.ty == TypeFlag::Bool {
157 Ok(self.data != 0)
158 } else {
159 Err("invalid type")
160 }
161 }
162}
163
164impl TryInto<bool> for &Value {
165 type Error = &'static str;
166
167 fn try_into(self) -> Result<bool, Self::Error> {
168 if self.ty == TypeFlag::Bool {
169 Ok(self.data != 0)
170 } else {
171 Err("invalid type")
172 }
173 }
174}
175
176impl_try_into_value!(u8, U8);
177impl_try_into_value!(u16, U16);
178impl_try_into_value!(u32, U32);
179impl_try_into_value!(u64, U64);
180
181impl TryInto<f32> for Value {
182 type Error = &'static str;
183
184 fn try_into(self) -> Result<f32, Self::Error> {
185 if self.ty == TypeFlag::F32 {
186 Ok(f32::from_bits(self.data as u32))
187 } else {
188 Err("invalid type")
189 }
190 }
191}
192
193impl TryInto<f32> for &Value {
194 type Error = &'static str;
195
196 fn try_into(self) -> Result<f32, Self::Error> {
197 if self.ty == TypeFlag::F32 {
198 Ok(f32::from_bits(self.data as u32))
199 } else {
200 Err("invalid type")
201 }
202 }
203}
204
205impl TryInto<f64> for Value {
206 type Error = &'static str;
207
208 fn try_into(self) -> Result<f64, Self::Error> {
209 if self.ty == TypeFlag::F64 {
210 Ok(f64::from_bits(self.data))
211 } else {
212 Err("invalid type")
213 }
214 }
215}
216
217impl TryInto<f64> for &Value {
218 type Error = &'static str;
219
220 fn try_into(self) -> Result<f64, Self::Error> {
221 if self.ty == TypeFlag::F64 {
222 Ok(f64::from_bits(self.data))
223 } else {
224 Err("invalid type")
225 }
226 }
227}
228
229macro_rules! impl_arith_ops {
230 ($trait:path, $fn_name:ident, $op:tt) => {
231 impl $trait for Value {
232 type Output = Self;
233
234 fn $fn_name(self, rhs: Self) -> Self::Output {
235 use TypeFlag::*;
236 match (self.ty, rhs.ty) {
237 (I8, I8) => {
238 let lhs: i8 = self.try_into().unwrap();
239 let rhs: i8 = rhs.try_into().unwrap();
240 (lhs $op rhs).into()
241 }
242 (I16, I16) => {
243 let lhs: i16 = self.try_into().unwrap();
244 let rhs: i16 = rhs.try_into().unwrap();
245 (lhs $op rhs).into()
246 }
247 (I32, I32) => {
248 let lhs: i32 = self.try_into().unwrap();
249 let rhs: i32 = rhs.try_into().unwrap();
250 (lhs $op rhs).into()
251 }
252 (I64, I64) => {
253 let lhs: i64 = self.try_into().unwrap();
254 let rhs: i64 = rhs.try_into().unwrap();
255 (lhs $op rhs).into()
256 }
257 (F32, F32) => {
258 let lhs: f32 = self.try_into().unwrap();
259 let rhs: f32 = rhs.try_into().unwrap();
260 (lhs $op rhs).into()
261 }
262 (F64, F64) => {
263 let lhs: f64 = self.try_into().unwrap();
264 let rhs: f64 = rhs.try_into().unwrap();
265 (lhs $op rhs).into()
266 }
267 (U8, U8) => {
268 let lhs: u8 = self.try_into().unwrap();
269 let rhs: u8 = rhs.try_into().unwrap();
270 (lhs $op rhs).into()
271 }
272 (U16, U16) => {
273 let lhs: u16 = self.try_into().unwrap();
274 let rhs: u16 = rhs.try_into().unwrap();
275 (lhs $op rhs).into()
276 }
277 (U32, U32) => {
278 let lhs: u32 = self.try_into().unwrap();
279 let rhs: u32 = rhs.try_into().unwrap();
280 (lhs $op rhs).into()
281 }
282 (U64, U64) => {
283 let lhs: u64 = self.try_into().unwrap();
284 let rhs: u64 = rhs.try_into().unwrap();
285 (lhs $op rhs).into()
286 }
287 _ => panic!("invalid types"),
288 }
289 }
290 }
291 };
292}
293
294impl_arith_ops!(std::ops::Add, add, +);
295impl_arith_ops!(std::ops::Sub, sub, -);
296impl_arith_ops!(std::ops::Mul, mul, *);
297impl_arith_ops!(std::ops::Div, div, /);
298impl_arith_ops!(std::ops::Rem, rem, %);
299
300macro_rules! impl_bit_ops {
301 ($trait:path, $fn_name:ident, $op:tt) => {
302 impl $trait for Value {
303 type Output = Self;
304
305 fn $fn_name(self, rhs: Self) -> Self::Output {
306 use TypeFlag::*;
307
308 match (self.ty, rhs.ty) {
309 (I8, I8) => {
310 let lhs: i8 = self.try_into().unwrap();
311 let rhs: i8 = rhs.try_into().unwrap();
312 (lhs $op rhs).into()
313 }
314 (I16, I16) => {
315 let lhs: i16 = self.try_into().unwrap();
316 let rhs: i16 = rhs.try_into().unwrap();
317 (lhs $op rhs).into()
318 }
319 (I32, I32) => {
320 let lhs: i32 = self.try_into().unwrap();
321 let rhs: i32 = rhs.try_into().unwrap();
322 (lhs $op rhs).into()
323 }
324 (I64, I64) => {
325 let lhs: i64 = self.try_into().unwrap();
326 let rhs: i64 = rhs.try_into().unwrap();
327 (lhs $op rhs).into()
328 }
329 (U8, U8) => {
330 let lhs: u8 = self.try_into().unwrap();
331 let rhs: u8 = rhs.try_into().unwrap();
332 (lhs $op rhs).into()
333 }
334 (U16, U16) => {
335 let lhs: u16 = self.try_into().unwrap();
336 let rhs: u16 = rhs.try_into().unwrap();
337 (lhs $op rhs).into()
338 }
339 (U32, U32) => {
340 let lhs: u32 = self.try_into().unwrap();
341 let rhs: u32 = rhs.try_into().unwrap();
342 (lhs $op rhs).into()
343 }
344 (U64, U64) => {
345 let lhs: u64 = self.try_into().unwrap();
346 let rhs: u64 = rhs.try_into().unwrap();
347 (lhs $op rhs).into()
348 }
349 _ => panic!("invalid types"),
350 }
351 }
352 }
353 };
354}
355
356impl_bit_ops!(std::ops::BitAnd, bitand, &);
357impl_bit_ops!(std::ops::BitOr, bitor, |);
358impl_bit_ops!(std::ops::BitXor, bitxor, ^);
359impl_bit_ops!(std::ops::Shl, shl, <<);
360impl_bit_ops!(std::ops::Shr, shr, >>);
361
362impl std::ops::Not for Value {
363 type Output = Self;
364
365 fn not(self) -> Self::Output {
366 use TypeFlag::*;
367
368 match self.ty {
369 I8 => {
370 let lhs: i8 = self.try_into().unwrap();
371 (!lhs).into()
372 }
373 I16 => {
374 let lhs: i16 = self.try_into().unwrap();
375 (!lhs).into()
376 }
377 I32 => {
378 let lhs: i32 = self.try_into().unwrap();
379 (!lhs).into()
380 }
381 I64 => {
382 let lhs: i64 = self.try_into().unwrap();
383 (!lhs).into()
384 }
385 U8 => {
386 let lhs: u8 = self.try_into().unwrap();
387 (!lhs).into()
388 }
389 U16 => {
390 let lhs: u16 = self.try_into().unwrap();
391 (!lhs).into()
392 }
393 U32 => {
394 let lhs: u32 = self.try_into().unwrap();
395 (!lhs).into()
396 }
397 U64 => {
398 let lhs: u64 = self.try_into().unwrap();
399 (!lhs).into()
400 }
401 Bool => {
402 let lhs: bool = self.try_into().unwrap();
403 (!lhs).into()
404 }
405 _ => panic!("invalid types"),
406 }
407 }
408}
409
410impl std::ops::Neg for Value {
411 type Output = Self;
412
413 fn neg(self) -> Self::Output {
414 use TypeFlag::*;
415
416 match self.ty {
417 I8 => {
418 let lhs: i8 = self.try_into().unwrap();
419 (-lhs).into()
420 }
421 I16 => {
422 let lhs: i16 = self.try_into().unwrap();
423 (-lhs).into()
424 }
425 I32 => {
426 let lhs: i32 = self.try_into().unwrap();
427 (-lhs).into()
428 }
429 I64 => {
430 let lhs: i64 = self.try_into().unwrap();
431 (-lhs).into()
432 }
433 F32 => {
434 let lhs: f32 = self.try_into().unwrap();
435 (-lhs).into()
436 }
437 F64 => {
438 let lhs: f64 = self.try_into().unwrap();
439 (-lhs).into()
440 }
441 _ => panic!("invalid types"),
442 }
443 }
444}
445
446impl std::cmp::PartialEq for Value {
447 fn eq(&self, other: &Self) -> bool {
448 if self.ty == other.ty {
449 return self.data == other.data;
450 }
451 return false;
452 }
453
454 fn ne(&self, other: &Self) -> bool {
455 if self.ty == other.ty {
456 return self.data != other.data;
457 }
458 return true;
459 }
460}
461
462impl std::cmp::PartialOrd for Value {
463 fn partial_cmp(&self, other: &Self) -> Option<std::cmp::Ordering> {
464 if self.ty == other.ty {
465 return self.data.partial_cmp(&other.data);
466 }
467 return None;
468 }
469}
470
471
472impl std::fmt::Display for Value {
473 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
474 use TypeFlag::*;
475
476 match self.ty {
477 I8 => {
478 let val: i8 = self.try_into().unwrap();
479 write!(f, "{}", val)
480 },
481 I16 => {
482 let val: i16 = self.try_into().unwrap();
483 write!(f, "{}", val)
484 },
485 I32 => {
486 let val: i32 = self.try_into().unwrap();
487 write!(f, "{}", val)
488 },
489 I64 => {
490 let val: i64 = self.try_into().unwrap();
491 write!(f, "{}", val)
492 },
493 U8 => {
494 let val: u8 = self.try_into().unwrap();
495 write!(f, "{}", val)
496 },
497 U16 => {
498 let val: u16 = self.try_into().unwrap();
499 write!(f, "{}", val)
500 },
501 U32 => {
502 let val: u32 = self.try_into().unwrap();
503 write!(f, "{}", val)
504 },
505 U64 => {
506 let val: u64 = self.try_into().unwrap();
507 write!(f, "{}", val)
508 },
509 F32 => {
510 let val: f32 = self.try_into().unwrap();
511 write!(f, "{}", val)
512 },
513 F64 => {
514 let val: f64 = self.try_into().unwrap();
515 write!(f, "{}", val)
516 },
517 Bool => {
518 let val: bool = self.try_into().unwrap();
519 write!(f, "{}", val)
520 },
521 Char => {
522 let val: char = self.try_into().unwrap();
523 write!(f, "{}", val)
524 },
525 }
526 }
527}
528
529impl Into<String> for Value {
530 fn into(self) -> String {
531 format!("{}", self)
532 }
533}
534
535
536
537#[cfg(test)]
538mod tests {
539 use super::*;
540
541 macro_rules! lifecycle_test {
554 ($type:ty, $flag:expr, $init:expr) => {
555 let init: $type = $init;
556 let value = Value::from(init);
557 let code: &[u8] = &value.to_code();
558 let decode = Value::from_code($flag, code);
559 let stack_push = decode.to_stack();
560 let stack_pop = Value::from_stack($flag, stack_push);
561 let prim_test: $type = stack_pop.try_into().unwrap();
562 assert_eq!(prim_test, init);
563 };
564 }
565
566 #[test]
567 fn test_i8_lifecycle() {
568 lifecycle_test!(i8, TypeFlag::I8, -100);
569 lifecycle_test!(i8, TypeFlag::I8, 126);
570 }
571
572 #[test]
573 fn test_i16_lifecycle() {
574 lifecycle_test!(i16, TypeFlag::I16, -20);
575 lifecycle_test!(i16, TypeFlag::I16, 12345);
576 }
577
578 #[test]
579 fn test_i32_lifecycle() {
580 lifecycle_test!(i32, TypeFlag::I32, 7895);
581 lifecycle_test!(i32, TypeFlag::I32, 1234567890);
582 }
583
584 #[test]
585 fn test_i64_lifecycle() {
586 lifecycle_test!(i64, TypeFlag::I64, 1234567890);
587 lifecycle_test!(i64, TypeFlag::I64, 1234567890123456789);
588 }
589
590 #[test]
591 fn test_f32_lifecycle() {
592 lifecycle_test!(f32, TypeFlag::F32, std::f32::consts::PI);
593 lifecycle_test!(f32, TypeFlag::F32, std::f32::consts::E);
594 }
595
596 #[test]
597 fn test_f64_lifecycle() {
598 lifecycle_test!(f64, TypeFlag::F64, std::f64::consts::PI);
599 lifecycle_test!(f64, TypeFlag::F64, std::f64::consts::E);
600 }
601
602 #[test]
603 fn test_bool_lifecycle() {
604 lifecycle_test!(bool, TypeFlag::Bool, true);
605 lifecycle_test!(bool, TypeFlag::Bool, false);
606 }
607
608 #[test]
609 fn test_char_lifecycle() {
610 lifecycle_test!(char, TypeFlag::Char, 'a');
611 lifecycle_test!(char, TypeFlag::Char, 'b');
612 lifecycle_test!(char, TypeFlag::Char, 'c');
613 }
614
615 #[test]
616 fn test_u8_lifecycle() {
617 lifecycle_test!(u8, TypeFlag::U8, 255);
618 lifecycle_test!(u8, TypeFlag::U8, 0);
619 lifecycle_test!(u8, TypeFlag::U8, 127);
620 }
621
622 #[test]
623 fn test_u16_lifecycle() {
624 lifecycle_test!(u16, TypeFlag::U16, 65535);
625 lifecycle_test!(u16, TypeFlag::U16, 0);
626 lifecycle_test!(u16, TypeFlag::U16, 32767);
627 }
628
629 #[test]
630 fn test_u32_lifecycle() {
631 lifecycle_test!(u32, TypeFlag::U32, 4294967295);
632 lifecycle_test!(u32, TypeFlag::U32, 0);
633 lifecycle_test!(u32, TypeFlag::U32, 2147483647);
634 }
635
636 #[test]
637 fn test_u64_lifecycle() {
638 lifecycle_test!(u64, TypeFlag::U64, 18446744073709551615);
639 lifecycle_test!(u64, TypeFlag::U64, 0);
640 lifecycle_test!(u64, TypeFlag::U64, 9223372036854775807);
641 }
642
643 macro_rules! bin_test {
650 ($type:ty, $lhs:expr, $rhs:expr, $op:tt) => {
651 let lhs = Value::from($lhs);
652 let rhs = Value::from($rhs);
653 let expected = Value::from($lhs $op $rhs);
654 let actual = lhs $op rhs;
655 assert_eq!(expected, actual);
656 };
657 }
658
659 macro_rules! all_arith_tests {
660 ($type:ty, $lhs:expr, $rhs:expr) => {
661 bin_test!($type, $lhs, $rhs, +);
662
663 bin_test!($type, $lhs, $rhs, -);
664
665 bin_test!($type, $lhs, $rhs, *);
666
667 bin_test!($type, $lhs, $rhs, /);
668
669 bin_test!($type, $lhs, $rhs, %);
670 };
671 }
672
673 #[test]
674 fn test_i8_arith() {
675 all_arith_tests!(i8, 2, 5);
676 all_arith_tests!(i8, 100, 1);
677 all_arith_tests!(i8, 20, 4);
678 }
679
680 #[test]
681 fn test_i16_artih() {
682 all_arith_tests!(i16, 20, 5);
683 all_arith_tests!(i16, 100, 20);
684 all_arith_tests!(i16, 3, 4);
685 }
686
687 #[test]
688 fn test_i32_arith() {
689 all_arith_tests!(i32, 88, 44);
690 all_arith_tests!(i32, 56, 8);
691 all_arith_tests!(i32, 100, 5);
692 }
693
694 #[test]
695 fn test_i64_arith() {
696 all_arith_tests!(i64, 100, 5);
697 all_arith_tests!(i64, 648, 111);
698 all_arith_tests!(i64, 86, 4);
699 }
700
701 #[test]
702 fn test_f32_arith() {
703 all_arith_tests!(f32, std::f32::consts::PI, 1.3456f32);
704 all_arith_tests!(f32, std::f32::consts::E, 13.7689f32);
705 all_arith_tests!(f32, 1.067f32, 1.12310f32);
706
707 }
708
709 #[test]
710 fn test_f64_arith() {
711 all_arith_tests!(f64, std::f64::consts::PI, 1.3456f64);
712 all_arith_tests!(f64, std::f64::consts::E, 13.7689f64);
713 all_arith_tests!(f64, 1.067f64, 1.12310f64);
714 }
715
716
717 #[test]
718 fn test_u8_arith() {
719 all_arith_tests!(u8, 100, 5);
720 all_arith_tests!(u8, 255, 1);
721 all_arith_tests!(u8, 86, 4);
722 }
723
724 #[test]
725 fn test_u16_arith() {
726 all_arith_tests!(u16, 100, 5);
727 all_arith_tests!(u16, 65535, 1);
728 all_arith_tests!(u16, 86, 4);
729 }
730
731 #[test]
732 fn test_u32_arith() {
733 all_arith_tests!(u32, 100, 5);
734 all_arith_tests!(u32, 586858, 1);
735 all_arith_tests!(u32, 86, 4);
736 }
737
738 #[test]
739 fn test_u64_arith() {
740 all_arith_tests!(u64, 100, 5);
741 all_arith_tests!(u64, 586858, 1);
742 all_arith_tests!(u64, 86, 4);
743 }
744
745 macro_rules! all_bit_tests {
748 ($type:ty, $lhs:expr, $rhs:expr) => {
749 bin_test!($type, $lhs, $rhs, &);
750 bin_test!($type, $lhs, $rhs, |);
751 bin_test!($type, $lhs, $rhs, ^);
752 };
753 }
754
755 #[test]
756 fn test_i8_bitops() {
757 all_bit_tests!(i8, 2i8, 100i8);
758 all_bit_tests!(i8, 20i8, 4i8);
759 all_bit_tests!(i8, 22i8, 5i8);
760 }
761
762 #[test]
763 fn test_i16_bitops() {
764 all_bit_tests!(i16, 100i16, 101i16);
765 all_bit_tests!(i16, 20i16, 4i16);
766 all_bit_tests!(i16, 22i16, 5i16);
767 }
768
769 #[test]
770 fn test_i32_bitops() {
771 all_bit_tests!(i32, 120i32, 55i32);
772 all_bit_tests!(i32, 20i32, 4i32);
773 all_bit_tests!(i32, 22i32, 5i32);
774 }
775
776 #[test]
777 fn test_i64_bitops() {
778 all_bit_tests!(i64, 100i64, 50i64);
779 all_bit_tests!(i64, 20i64, 4i64);
780 all_bit_tests!(i64, 26i64, 100i64);
781 }
782
783 #[test]
784 fn test_u8_bitops() {
785 all_bit_tests!(u8, 100u8, 50u8);
786 all_bit_tests!(u8, 20u8, 4u8);
787 all_bit_tests!(u8, 2u8, 5u8);
788 }
789
790 #[test]
791 fn test_u16_bitops() {
792 all_bit_tests!(u16, 100u16, 50u16);
793 all_bit_tests!(u16, 20u16, 4u16);
794 all_bit_tests!(u16, 2u16, 5u16);
795 }
796
797 #[test]
798 fn test_u32_bitops() {
799 all_bit_tests!(u32, 100u32, 50u32);
800 all_bit_tests!(u32, 20u32, 4u32);
801 all_bit_tests!(u32, 2u32, 5u32);
802 }
803
804 #[test]
805 fn test_u64_bitops() {
806 all_bit_tests!(u64, 100u64, 50u64);
807 all_bit_tests!(u64, 20u64, 4u64);
808 all_bit_tests!(u64, 2u64, 5u64);
809 }
810 macro_rules! shift_tests {
813 ($type:ty, $lhs:expr, $rhs:expr) => {
814 bin_test!($type, $lhs, $rhs, <<);
815 bin_test!($type, $lhs, $rhs, >>);
816 };
817 }
818
819 #[test]
820 fn test_i8_shift() {
821 shift_tests!(i8, 100i8, 3i8);
822 shift_tests!(i8, 20i8, 4i8);
823 shift_tests!(i8, 22i8, 5i8);
824 }
825
826 #[test]
827 fn test_i16_shift() {
828 shift_tests!(i16, 100i16, 3i16);
829 shift_tests!(i16, 20i16, 4i16);
830 shift_tests!(i16, 22i16, 5i16);
831 }
832
833 #[test]
834 fn test_i32_shift() {
835 shift_tests!(i32, 100i32, 3i32);
836 shift_tests!(i32, 20i32, 4i32);
837 shift_tests!(i32, 22i32, 5i32);
838 }
839
840 #[test]
841 fn test_i64_shift() {
842 shift_tests!(i64, 100i64, 3i64);
843 shift_tests!(i64, 20i64, 4i64);
844 shift_tests!(i64, 22i64, 5i64);
845 }
846
847 #[test]
848 fn test_u8_shift() {
849 shift_tests!(u8, 100u8, 3u8);
850 shift_tests!(u8, 20u8, 4u8);
851 shift_tests!(u8, 22u8, 5u8);
852 }
853
854 #[test]
855 fn test_u16_shift() {
856 shift_tests!(u16, 100u16, 3u16);
857 shift_tests!(u16, 20u16, 4u16);
858 shift_tests!(u16, 22u16, 5u16);
859 }
860
861 #[test]
862 fn test_u32_shift() {
863 shift_tests!(u32, 100u32, 3u32);
864 shift_tests!(u32, 20u32, 4u32);
865 shift_tests!(u32, 22u32, 5u32);
866 }
867
868 #[test]
869 fn test_u64_shift() {
870 shift_tests!(u64, 100u64, 3u64);
871 shift_tests!(u64, 20u64, 4u64);
872 shift_tests!(u64, 22u64, 5u64);
873 }
874
875 macro_rules! unary_test {
878 ($type:ty, $val:expr, $op:tt) => {
879 let value = Value::from($val);
880 let expected = Value::from($op$val);
881 let actual = $op value;
882 assert_eq!(expected, actual);
883 };
884 }
885
886 macro_rules! not_tests {
887 ($type:ty, $val:expr) => {
888 unary_test!($type, $val, !);
889 };
890 }
891
892 #[test]
893 fn test_i8_not() {
894 not_tests!(i8, 100i8);
895 not_tests!(i8, 20i8);
896 not_tests!(i8, 22i8);
897 }
898
899 #[test]
900 fn test_i16_not() {
901 not_tests!(i16, 1245i16);
902 not_tests!(i16, 1005i16);
903 }
904
905 #[test]
906 fn test_i32_not() {
907 not_tests!(i32, 10000i32);
908 not_tests!(i32, 5000i32);
909 }
910
911 #[test]
912 fn test_i64_not() {
913 not_tests!(i64, 100000i64);
914 not_tests!(i64, 50000i64);
915 }
916
917 #[test]
918 fn test_u8_not() {
919 not_tests!(u8, 100u8);
920 not_tests!(u8, 20u8);
921 not_tests!(u8, std::u8::MAX);
922 not_tests!(u8, std::u8::MIN);
923 }
924
925 #[test]
926 fn test_u16_not() {
927 not_tests!(u16, 1000u16);
928 not_tests!(u16, 2000u16);
929 not_tests!(u16, std::u16::MAX);
930 not_tests!(u16, std::u16::MIN);
931 }
932
933 #[test]
934 fn test_u32_not() {
935 not_tests!(u32, std::u32::MAX);
936 not_tests!(u32, std::u32::MIN);
937 }
938
939 #[test]
940 fn test_u64_not() {
941 not_tests!(u64, std::u64::MAX);
942 not_tests!(u64, std::u64::MIN);
943 }
944
945 #[test]
946 fn test_bool_not() {
947 not_tests!(bool, true);
948 not_tests!(bool, false);
949 }
950
951 macro_rules! neg_tests {
954 ($type:ty, $val:expr) => {
955 unary_test!($type, $val, -);
956 };
957 }
958
959
960 #[test]
961 fn test_i8_neg() {
962 neg_tests!(i8, 100i8);
963 neg_tests!(i8, -20i8);
964 }
965
966 #[test]
967 fn test_i16_neg() {
968 neg_tests!(i16, 1245i16);
969 neg_tests!(i16, -1005i16);
970 }
971
972 #[test]
973 fn test_i32_neg() {
974 neg_tests!(i32, 10000i32);
975 neg_tests!(i32, -5000i32);
976 }
977
978 #[test]
979 fn test_i64_neg() {
980 neg_tests!(i64, 100000i64);
981 neg_tests!(i64, -50000i64);
982 }
983
984 #[test]
985 fn test_f32_neg() {
986 neg_tests!(f32, std::f32::consts::PI);
987 neg_tests!(f32, -std::f32::consts::E);
988 }
989
990 #[test]
991 fn test_f64_neg() {
992 neg_tests!(f64, std::f64::consts::PI);
993 neg_tests!(f64, -std::f64::consts::E);
994 }
995
996 #[test]
997 fn test_to_string() {
998 assert_eq!(Value::from(10).to_string(), "10".to_string());
999 assert_eq!(Value::from('c').to_string(), "c".to_string());
1000 }
1001}