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
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
/// Generates a Rust enum with a custom range of values, including variants for
/// named values, custom values within a specified range, and reserved values
/// outside that range.
///
/// This macro is particularly useful for creating BACnet-related enums where
/// standard values are enumerated, but custom or proprietary values might also
/// exist within or outside a defined range.
///
/// # Arguments
///
/// * `$name:ident` - The name of the enum to be generated.
/// * `$variant:ident = $value:expr` - A comma-separated list of named enum
/// variants and their corresponding integer values.
/// * `$unit:ident` - The underlying integer type for the enum (e.g., `u8`, `u16`, `u32`).
/// * `$range:expr` - An expression representing the valid custom range (e.g., `1000..=2000`).
/// Values within this range that are not explicitly named variants will be
/// represented by the `Custom` variant.
///
/// # Example
///
/// ```rust
/// use bacnet_rs::generate_custom_enum;
///
/// generate_custom_enum! {
/// MyEnum {
/// VariantA = 1,
/// VariantB = 2,
/// VariantC = 100,
/// },
/// u16,
/// 1000..=2000
/// }
///
/// // Usage
/// let a = MyEnum::VariantA;
/// let custom_val = MyEnum::from(1500u16); // Will be MyEnum::Custom{ value: 1500 }
/// let reserved_val = MyEnum::from(3000u16); // Will be MyEnum::Reserved{ value: 3000 }
/// let named_val = MyEnum::from(100u16); // Will be MyEnum::VariantC
///
/// assert_eq!(u16::from(a), 1);
/// assert_eq!(format!("{}", a), "VariantA");
/// if let MyEnum::Custom( value ) = custom_val {
/// assert_eq!(value.value(), 1500);
/// } else {
/// panic!("Expected MyEnum::Custom");
/// }
/// if let MyEnum::Reserved( value ) = reserved_val {
/// assert_eq!(value.value(), 3000);
/// } else {
/// panic!("Expected MyEnum::Reserved");
/// }
/// assert_eq!(named_val, MyEnum::VariantC);
/// ```
///
/// # Generated Code Structure
///
/// The macro generates an enum with the following variants:
///
/// * `$(variant:ident),*` - The named variants provided by the user.
/// * `Custom { value: $unit }` - Represents values within the specified `$range`
/// that do not correspond to any named variant.
/// * `Reserved { value: $unit }` - Represents values outside the specified
/// `$range` (and not named variants).
///
/// It also implements:
///
/// * `Debug`, `Clone`, `Copy`, `PartialEq`, `Eq`, `Hash` for the enum.
/// * `std::fmt::Display` for human-readable string representation.
/// - Named variants display their name.
/// - `Custom` variants display as `Custom(value)`.
/// - `Reserved` variants display as `Reserved(value)`.
/// * `From<$name> for $unit` for easy conversion from the enum to its underlying integer type.
/// * `From<$unit> for $name` for easy conversion from the underlying integer type to the enum,
/// handling named, custom, and reserved values appropriately based on the `$range`.