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
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
use Display;
use HashMap;
use Mutex;
use ;
/// Represents different encoding strategies for J1939 message fields.
///
/// This enum defines how field values are encoded into and decoded from the raw bit stream
/// of a J1939 message. Each encoding type has specific behavior for marshalling (encoding)
/// and unmarshalling (decoding) operations.
///
/// # Encoding Types
///
/// ## `UInt` - Unsigned Integer
///
/// Direct unsigned integer encoding with no transformation.
/// - **Used for**: `u8`, `u16`, `u32` field types
/// - **Marshall**: Direct bit packing as unsigned value
/// - **Unmarshall**: Direct bit extraction as unsigned value
/// - **Example**:
/// ```ignore
/// #[j1939(bits = 0..8)]
/// pub counter: u8, // Automatically inferred as UInt
/// ```
///
/// ## `SInt` - Signed Integer
///
/// Signed integer encoding with sign extension for negative values.
/// - **Used for**: `i8`, `i16`, `i32` field types
/// - **Marshall**: Two's complement representation
/// - **Unmarshall**: Sign extension applied to extract signed value
/// - **Example**:
/// ```ignore
/// #[j1939(bits = 0..16)]
/// pub temperature_delta: i16, // Automatically inferred as SInt
/// ```
///
/// ## `Scaled` - Scaled Float with Optional Offset
///
/// Float encoding with linear transformation: `physical_value = (raw * scale) + offset`
/// - **Used for**: `f32` fields with `scale` attribute
/// - **Parameters**:
/// - `scale`: Multiplicative scaling factor (required)
/// - `offset`: Additive offset (optional, defaults to 0.0)
/// - **Marshall formula**: `raw = (physical_value - offset) / scale`
/// - **Unmarshall formula**: `physical_value = (raw * scale) + offset`
/// - **Signedness**:
/// - When `offset != 0.0`: Raw values treated as unsigned
/// - When `offset == 0.0`: Sign extension applied for negative values
/// - **Examples**:
/// ```ignore
/// // Simple scaling without offset
/// #[j1939(bits = 0..16, scale = 0.125, unit = "rpm")]
/// pub engine_speed: f32, // 0.125 RPM per bit
///
/// // Scaling with offset (e.g., temperature)
/// #[j1939(bits = 16..24, scale = 1.0, offset = -40.0, unit = "°C")]
/// pub coolant_temp: f32, // -40°C to +215°C range
///
/// // Torque percentage with negative offset
/// #[j1939(bits = 8..16, scale = 1.0, offset = -125.0, unit = "%")]
/// pub torque: f32, // -125% to +125% range
/// ```
///
/// ## `Q9` - Fixed-Point Q9 Format
///
/// Q9 fixed-point encoding for high-precision fractional values in limited bit space.
/// - **Used for**: `f32` fields with `encoding = "q9"` attribute
/// - **Format**: 1 sign bit + 9 fractional bits (10 bits total)
/// - **Range**: Approximately -1.0 to +1.0
/// - **Precision**: 1/512 ≈ 0.00195
/// - **Example**:
/// ```ignore
/// #[j1939(bits = 0..10, encoding = "q9")]
/// pub control_gain: f32, // High precision control value
/// ```
///
/// ## `Enum` - Enumeration Type
///
/// Type-safe enum encoding using the enum's discriminant value.
/// - **Used for**: Custom enum types (automatically detected)
/// - **Requirements**: Enum must be `#[repr(u8)]` and marked with `#[j1939_enum]`
/// - **Marshall**: Uses enum discriminant as raw value
/// - **Unmarshall**: Transmutes raw value back to enum (unsafe but fast)
/// - **Example**:
/// ```ignore
/// #[repr(u8)]
/// #[j1939_enum]
/// pub enum GearPosition {
/// Park = 0,
/// Drive = 1,
/// }
///
/// #[j1939(bits = 0..2)]
/// pub gear: GearPosition, // Automatically inferred as Enum
/// ```
///
/// ## `Reserved` - Reserved/Unused Bits
///
/// Marks bits as reserved or unused in the message.
/// - **Used for**: Field types with `reserved` flag
/// - **Marshall**: Sets bits to zero
/// - **Unmarshall**: Returns unit type `()`
/// - **Purpose**: Ensures complete bit coverage and future compatibility
/// - **Example**:
/// ```ignore
/// #[j1939(bits = 24..64, reserved)]
/// pub reserved: (),
/// ```
///
/// # Selection Logic
///
/// The encoding type is determined automatically based on:
/// 1. If `reserved` flag is present → `Reserved`
/// 2. If `encoding = "q9"` → `Q9`
/// 3. If `scale` is present → `Scaled { scale, offset }`
/// 4. Otherwise inferred from Rust type:
/// - `f32`/`f64` without scale → Error (must specify scale or encoding)
/// - `i8`/`i16`/`i32` → `SInt`
/// - `u8`/`u16`/`u32` → `UInt`
/// - Other types → `Enum`
///
/// # See Also
///
/// - [`j1939_message`](crate::j1939_message) - The attribute macro that uses these encodings
/// - [`j1939_enum`](crate::j1939_enum) - For registering enums used with `Encoding::Enum`
// Global registry for storing enum information during compilation
static ENUM_REGISTRY: = new;