1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
use crate::core;
use proc_macro2::TokenStream;
use quote::quote;
use std::{cmp::Ordering, ops::RangeInclusive};
pub fn impl_from(range: &RangeInclusive<u32>) -> TokenStream {
let mut impls = Vec::new();
for n_1 in range.clone() {
for is_signed_1 in [false, true] {
let flag_name_1 = core::feature_name(n_1, is_signed_1);
//let ty_1 = core::inner_type(n_1, is_signed_1);
let struct_name_1 = core::struct_name(n_1, is_signed_1);
let shift_1 = core::shift(n_1);
for n_2 in range.clone() {
for is_signed_2 in [false, true] {
let flag_name_2 = core::feature_name(n_2, is_signed_2);
let ty_2 = core::inner_type(n_2, is_signed_2);
let struct_name_2 = core::struct_name(n_2, is_signed_2);
if is_signed_1 == is_signed_2 {
impls.push(match n_1.cmp(&n_2) {
Ordering::Equal => {
continue;
}
Ordering::Less => {
if let Some(ref shift) = shift_1 {
quote! {
#[cfg(all(feature = #flag_name_1, feature = #flag_name_2))]
impl From<#struct_name_1> for #struct_name_2 {
fn from(value: #struct_name_1) -> Self {
let value = value.0 >> #shift;
#struct_name_2::new(
value as #ty_2
)
}
}
}
} else {
quote! {
#[cfg(all(feature = #flag_name_1, feature = #flag_name_2))]
impl From<#struct_name_1> for #struct_name_2 {
fn from(value: #struct_name_1) -> Self {
#struct_name_2::new(
value.0.into()
)
}
}
}
}
}
Ordering::Greater => {
let shift_2 = core::shift(n_2);
let shifted = if let Some(ref shift) = shift_2 {
quote! {
let value: #ty_2 = value;
if (<Self as num_traits::Bounded>::min_value().0 >> #shift) <= value && value <= (<Self as num_traits::Bounded>::max_value().0 >> #shift) {
Ok(#struct_name_2::new(value))
} else {
Err(ConvertError)
}
}
} else {
quote! {
Ok(#struct_name_2::new(value))
}
};
if let Some(ref shift) = shift_1 {
quote! {
#[cfg(all(feature = #flag_name_1, feature = #flag_name_2))]
impl TryFrom<#struct_name_1> for #struct_name_2 {
type Error = ConvertError;
fn try_from(value: #struct_name_1) -> Result<Self, Self::Error> {
if let Ok(value) = (value.0 >> #shift).try_into() {
#shifted
} else {
Err(ConvertError)
}
}
}
}
} else {
quote! {
#[cfg(all(feature = #flag_name_1, feature = #flag_name_2))]
impl TryFrom<#struct_name_1> for #struct_name_2 {
type Error = ConvertError;
fn try_from(value: #struct_name_1) -> Result<Self, Self::Error> {
if let Ok(value) = value.0.try_into() {
#shifted
} else {
Err(ConvertError)
}
}
}
}
}
}
});
} else {
impls.push(match n_1.cmp(&n_2) {
Ordering::Equal => {
quote! {
#[cfg(all(feature = #flag_name_1, feature = #flag_name_2))]
impl From<#struct_name_1> for #struct_name_2 {
fn from(value: #struct_name_1) -> Self {
#struct_name_2(
value.0 as #ty_2
)
}
}
}
}
Ordering::Less => {
continue;
}
Ordering::Greater => {
continue;
}
});
}
}
}
}
}
impls.into_iter().collect()
}