1use crate::error;
2use crate::UntaggedEnumVisitor;
3use serde::de::{Unexpected, Visitor};
4
5pub(crate) enum IntKind {
6 I8,
7 I16,
8 I32,
9 I64,
10 I128,
11 U8,
12 U16,
13 U32,
14 U64,
15 U128,
16}
17
18pub(crate) trait Integer:
19 Copy
20 + TryInto<i8>
21 + TryInto<i16>
22 + TryInto<i32>
23 + TryInto<i64>
24 + TryInto<i128>
25 + TryInto<u8>
26 + TryInto<u16>
27 + TryInto<u32>
28 + TryInto<u64>
29 + TryInto<u128>
30{
31}
32
33impl<T> Integer for T
34where
35 T: Copy,
36 i8: TryFrom<T>,
37 i16: TryFrom<T>,
38 i32: TryFrom<T>,
39 i64: TryFrom<T>,
40 i128: TryFrom<T>,
41 u8: TryFrom<T>,
42 u16: TryFrom<T>,
43 u32: TryFrom<T>,
44 u64: TryFrom<T>,
45 u128: TryFrom<T>,
46{
47}
48
49impl<'closure, 'de, Value> UntaggedEnumVisitor<'closure, 'de, Value> {
50 pub(crate) fn dispatch_integer<I, E>(
51 self,
52 value: I,
53 precedence: [IntKind; 10],
54 ) -> Result<Value, E>
55 where
56 I: Integer,
57 E: serde::de::Error,
58 {
59 for kind in precedence {
60 match kind {
61 IntKind::I8 => {
62 if let Some(int) = i8::int_from(value) {
63 if let Some(visit_i8) = self.visit_i8 {
64 return visit_i8(int).map_err(error::unerase);
65 }
66 }
67 }
68 IntKind::I16 => {
69 if let Some(int) = i16::int_from(value) {
70 if let Some(visit_i16) = self.visit_i16 {
71 return visit_i16(int).map_err(error::unerase);
72 }
73 }
74 }
75 IntKind::I32 => {
76 if let Some(int) = i32::int_from(value) {
77 if let Some(visit_i32) = self.visit_i32 {
78 return visit_i32(int).map_err(error::unerase);
79 }
80 }
81 }
82 IntKind::I64 => {
83 if let Some(int) = i64::int_from(value) {
84 if let Some(visit_i64) = self.visit_i64 {
85 return visit_i64(int).map_err(error::unerase);
86 }
87 }
88 }
89 IntKind::I128 => {
90 if let Some(int) = i128::int_from(value) {
91 if let Some(visit_i128) = self.visit_i128 {
92 return visit_i128(int).map_err(error::unerase);
93 }
94 }
95 }
96 IntKind::U8 => {
97 if let Some(int) = u8::int_from(value) {
98 if let Some(visit_u8) = self.visit_u8 {
99 return visit_u8(int).map_err(error::unerase);
100 }
101 }
102 }
103 IntKind::U16 => {
104 if let Some(int) = u16::int_from(value) {
105 if let Some(visit_u16) = self.visit_u16 {
106 return visit_u16(int).map_err(error::unerase);
107 }
108 }
109 }
110 IntKind::U32 => {
111 if let Some(int) = u32::int_from(value) {
112 if let Some(visit_u32) = self.visit_u32 {
113 return visit_u32(int).map_err(error::unerase);
114 }
115 }
116 }
117 IntKind::U64 => {
118 if let Some(int) = u64::int_from(value) {
119 if let Some(visit_u64) = self.visit_u64 {
120 return visit_u64(int).map_err(error::unerase);
121 }
122 }
123 }
124 IntKind::U128 => {
125 if let Some(int) = u128::int_from(value) {
126 if let Some(visit_u128) = self.visit_u128 {
127 return visit_u128(int).map_err(error::unerase);
128 }
129 }
130 }
131 }
132 }
133 if let Some(int) = u64::int_from(value) {
134 return Err(E::invalid_type(Unexpected::Unsigned(int), &self));
135 }
136 if let Some(int) = i64::int_from(value) {
137 return Err(E::invalid_type(Unexpected::Signed(int), &self));
138 }
139 if let Some(int) = u128::int_from(value) {
140 return crate::DefaultVisitor::new(&self).visit_u128(int);
141 }
142 if let Some(int) = i128::int_from(value) {
143 return crate::DefaultVisitor::new(&self).visit_i128(int);
144 }
145 unreachable!()
146 }
147}
148
149trait IntFrom<I>: Sized {
150 fn int_from(int: I) -> Option<Self>;
151}
152
153impl<T, I> IntFrom<I> for T
154where
155 I: TryInto<Self>,
156{
157 fn int_from(int: I) -> Option<Self> {
158 int.try_into().ok()
159 }
160}