1use serde::{Deserialize, Serialize};
4use std::fmt;
5
6#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)]
8#[serde(untagged)]
9#[derive(Default)]
10pub enum Value {
11 Bool(bool),
13 I8(i8),
15 U8(u8),
17 I16(i16),
19 U16(u16),
21 I32(i32),
23 U32(u32),
25 I64(i64),
27 U64(u64),
29 F32(f32),
31 F64(f64),
33 String(String),
35 Bytes(Vec<u8>),
37 Array(Vec<Value>),
39 #[default]
41 Null,
42}
43
44impl Value {
45 pub fn bool(v: bool) -> Self {
47 Self::Bool(v)
48 }
49
50 pub fn float(v: f64) -> Self {
52 Self::F64(v)
53 }
54
55 pub fn int(v: i64) -> Self {
57 Self::I64(v)
58 }
59
60 pub fn string(v: impl Into<String>) -> Self {
62 Self::String(v.into())
63 }
64
65 pub fn as_bool(&self) -> Option<bool> {
67 match self {
68 Self::Bool(v) => Some(*v),
69 Self::I8(v) => Some(*v != 0),
70 Self::U8(v) => Some(*v != 0),
71 Self::I16(v) => Some(*v != 0),
72 Self::U16(v) => Some(*v != 0),
73 Self::I32(v) => Some(*v != 0),
74 Self::U32(v) => Some(*v != 0),
75 Self::I64(v) => Some(*v != 0),
76 Self::U64(v) => Some(*v != 0),
77 _ => None,
78 }
79 }
80
81 pub fn as_f64(&self) -> Option<f64> {
83 match self {
84 Self::Bool(v) => Some(if *v { 1.0 } else { 0.0 }),
85 Self::I8(v) => Some(*v as f64),
86 Self::U8(v) => Some(*v as f64),
87 Self::I16(v) => Some(*v as f64),
88 Self::U16(v) => Some(*v as f64),
89 Self::I32(v) => Some(*v as f64),
90 Self::U32(v) => Some(*v as f64),
91 Self::I64(v) => Some(*v as f64),
92 Self::U64(v) => Some(*v as f64),
93 Self::F32(v) => Some(*v as f64),
94 Self::F64(v) => Some(*v),
95 _ => None,
96 }
97 }
98
99 pub fn as_i64(&self) -> Option<i64> {
101 match self {
102 Self::Bool(v) => Some(if *v { 1 } else { 0 }),
103 Self::I8(v) => Some(*v as i64),
104 Self::U8(v) => Some(*v as i64),
105 Self::I16(v) => Some(*v as i64),
106 Self::U16(v) => Some(*v as i64),
107 Self::I32(v) => Some(*v as i64),
108 Self::U32(v) => Some(*v as i64),
109 Self::I64(v) => Some(*v),
110 Self::U64(v) => i64::try_from(*v).ok(),
111 Self::F32(v) => Some(*v as i64),
112 Self::F64(v) => Some(*v as i64),
113 _ => None,
114 }
115 }
116
117 pub fn as_u16(&self) -> Option<u16> {
119 self.as_i64().and_then(|v| u16::try_from(v).ok())
120 }
121
122 pub fn as_str(&self) -> Option<&str> {
124 match self {
125 Self::String(v) => Some(v.as_str()),
126 _ => None,
127 }
128 }
129
130 pub fn as_bytes(&self) -> Option<&[u8]> {
132 match self {
133 Self::Bytes(v) => Some(v.as_slice()),
134 Self::String(v) => Some(v.as_bytes()),
135 _ => None,
136 }
137 }
138
139 pub fn is_numeric(&self) -> bool {
141 matches!(
142 self,
143 Self::I8(_)
144 | Self::U8(_)
145 | Self::I16(_)
146 | Self::U16(_)
147 | Self::I32(_)
148 | Self::U32(_)
149 | Self::I64(_)
150 | Self::U64(_)
151 | Self::F32(_)
152 | Self::F64(_)
153 )
154 }
155
156 pub fn is_null(&self) -> bool {
158 matches!(self, Self::Null)
159 }
160
161 pub fn type_name(&self) -> &'static str {
163 match self {
164 Self::Bool(_) => "bool",
165 Self::I8(_) => "i8",
166 Self::U8(_) => "u8",
167 Self::I16(_) => "i16",
168 Self::U16(_) => "u16",
169 Self::I32(_) => "i32",
170 Self::U32(_) => "u32",
171 Self::I64(_) => "i64",
172 Self::U64(_) => "u64",
173 Self::F32(_) => "f32",
174 Self::F64(_) => "f64",
175 Self::String(_) => "string",
176 Self::Bytes(_) => "bytes",
177 Self::Array(_) => "array",
178 Self::Null => "null",
179 }
180 }
181
182 pub fn to_registers(&self) -> Vec<u16> {
184 match self {
185 Self::Bool(v) => vec![if *v { 1 } else { 0 }],
186 Self::I8(v) => vec![*v as u16],
187 Self::U8(v) => vec![*v as u16],
188 Self::I16(v) => vec![*v as u16],
189 Self::U16(v) => vec![*v],
190 Self::I32(v) => {
191 let bytes = v.to_be_bytes();
192 vec![
193 u16::from_be_bytes([bytes[0], bytes[1]]),
194 u16::from_be_bytes([bytes[2], bytes[3]]),
195 ]
196 }
197 Self::U32(v) => {
198 let bytes = v.to_be_bytes();
199 vec![
200 u16::from_be_bytes([bytes[0], bytes[1]]),
201 u16::from_be_bytes([bytes[2], bytes[3]]),
202 ]
203 }
204 Self::F32(v) => {
205 let bytes = v.to_be_bytes();
206 vec![
207 u16::from_be_bytes([bytes[0], bytes[1]]),
208 u16::from_be_bytes([bytes[2], bytes[3]]),
209 ]
210 }
211 Self::F64(v) => {
212 let bytes = v.to_be_bytes();
213 vec![
214 u16::from_be_bytes([bytes[0], bytes[1]]),
215 u16::from_be_bytes([bytes[2], bytes[3]]),
216 u16::from_be_bytes([bytes[4], bytes[5]]),
217 u16::from_be_bytes([bytes[6], bytes[7]]),
218 ]
219 }
220 _ => vec![],
221 }
222 }
223
224 pub fn from_registers(registers: &[u16], value_type: ValueType) -> Option<Self> {
226 match value_type {
227 ValueType::Bool => registers.first().map(|r| Value::Bool(*r != 0)),
228 ValueType::U16 => registers.first().map(|r| Value::U16(*r)),
229 ValueType::I16 => registers.first().map(|r| Value::I16(*r as i16)),
230 ValueType::U32 if registers.len() >= 2 => {
231 let bytes = [registers[0].to_be_bytes(), registers[1].to_be_bytes()];
232 Some(Value::U32(u32::from_be_bytes([
233 bytes[0][0],
234 bytes[0][1],
235 bytes[1][0],
236 bytes[1][1],
237 ])))
238 }
239 ValueType::I32 if registers.len() >= 2 => {
240 let bytes = [registers[0].to_be_bytes(), registers[1].to_be_bytes()];
241 Some(Value::I32(i32::from_be_bytes([
242 bytes[0][0],
243 bytes[0][1],
244 bytes[1][0],
245 bytes[1][1],
246 ])))
247 }
248 ValueType::F32 if registers.len() >= 2 => {
249 let bytes = [registers[0].to_be_bytes(), registers[1].to_be_bytes()];
250 Some(Value::F32(f32::from_be_bytes([
251 bytes[0][0],
252 bytes[0][1],
253 bytes[1][0],
254 bytes[1][1],
255 ])))
256 }
257 ValueType::F64 if registers.len() >= 4 => {
258 let bytes: Vec<u8> = registers[..4]
259 .iter()
260 .flat_map(|r| r.to_be_bytes())
261 .collect();
262 Some(Value::F64(f64::from_be_bytes([
263 bytes[0], bytes[1], bytes[2], bytes[3], bytes[4], bytes[5], bytes[6], bytes[7],
264 ])))
265 }
266 _ => None,
267 }
268 }
269}
270
271impl fmt::Display for Value {
272 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
273 match self {
274 Self::Bool(v) => write!(f, "{}", v),
275 Self::I8(v) => write!(f, "{}", v),
276 Self::U8(v) => write!(f, "{}", v),
277 Self::I16(v) => write!(f, "{}", v),
278 Self::U16(v) => write!(f, "{}", v),
279 Self::I32(v) => write!(f, "{}", v),
280 Self::U32(v) => write!(f, "{}", v),
281 Self::I64(v) => write!(f, "{}", v),
282 Self::U64(v) => write!(f, "{}", v),
283 Self::F32(v) => write!(f, "{:.3}", v),
284 Self::F64(v) => write!(f, "{:.6}", v),
285 Self::String(v) => write!(f, "{}", v),
286 Self::Bytes(v) => write!(f, "[{} bytes]", v.len()),
287 Self::Array(v) => write!(f, "[{} items]", v.len()),
288 Self::Null => write!(f, "null"),
289 }
290 }
291}
292
293
294impl From<bool> for Value {
296 fn from(v: bool) -> Self {
297 Self::Bool(v)
298 }
299}
300
301impl From<i32> for Value {
302 fn from(v: i32) -> Self {
303 Self::I32(v)
304 }
305}
306
307impl From<u32> for Value {
308 fn from(v: u32) -> Self {
309 Self::U32(v)
310 }
311}
312
313impl From<i64> for Value {
314 fn from(v: i64) -> Self {
315 Self::I64(v)
316 }
317}
318
319impl From<u64> for Value {
320 fn from(v: u64) -> Self {
321 Self::U64(v)
322 }
323}
324
325impl From<f32> for Value {
326 fn from(v: f32) -> Self {
327 Self::F32(v)
328 }
329}
330
331impl From<f64> for Value {
332 fn from(v: f64) -> Self {
333 Self::F64(v)
334 }
335}
336
337impl From<String> for Value {
338 fn from(v: String) -> Self {
339 Self::String(v)
340 }
341}
342
343impl From<&str> for Value {
344 fn from(v: &str) -> Self {
345 Self::String(v.to_string())
346 }
347}
348
349impl From<Vec<u8>> for Value {
350 fn from(v: Vec<u8>) -> Self {
351 Self::Bytes(v)
352 }
353}
354
355#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash, Serialize, Deserialize)]
357#[serde(rename_all = "lowercase")]
358pub enum ValueType {
359 Bool,
360 I8,
361 U8,
362 I16,
363 U16,
364 I32,
365 U32,
366 I64,
367 U64,
368 F32,
369 F64,
370 String,
371 Bytes,
372}
373
374impl ValueType {
375 pub fn size_bytes(&self) -> usize {
377 match self {
378 Self::Bool | Self::I8 | Self::U8 => 1,
379 Self::I16 | Self::U16 => 2,
380 Self::I32 | Self::U32 | Self::F32 => 4,
381 Self::I64 | Self::U64 | Self::F64 => 8,
382 Self::String | Self::Bytes => 0, }
384 }
385
386 pub fn register_count(&self) -> usize {
388 match self {
389 Self::Bool | Self::I8 | Self::U8 | Self::I16 | Self::U16 => 1,
390 Self::I32 | Self::U32 | Self::F32 => 2,
391 Self::I64 | Self::U64 | Self::F64 => 4,
392 Self::String | Self::Bytes => 0,
393 }
394 }
395}
396
397#[cfg(test)]
398mod tests {
399 use super::*;
400
401 #[test]
402 fn test_value_conversion() {
403 let v = Value::F64(123.456);
404 assert!((v.as_f64().unwrap() - 123.456).abs() < 0.001);
405 assert_eq!(v.as_i64(), Some(123));
406 }
407
408 #[test]
409 fn test_value_to_registers() {
410 let v = Value::F32(1.5);
411 let regs = v.to_registers();
412 assert_eq!(regs.len(), 2);
413
414 let v2 = Value::from_registers(®s, ValueType::F32).unwrap();
415 assert!((v2.as_f64().unwrap() - 1.5).abs() < 0.001);
416 }
417
418 #[test]
419 fn test_value_display() {
420 assert_eq!(Value::Bool(true).to_string(), "true");
421 assert_eq!(Value::I32(42).to_string(), "42");
422 assert_eq!(Value::F64(3.14159).to_string(), "3.141590");
423 }
424}