1use crate::desc::{FieldDesc, PointDesc, ValueKind};
9
10#[derive(Clone, Copy, Debug, PartialEq)]
12pub enum Reading<T> {
13 Value(T),
14 Unavailable(&'static str),
15}
16
17impl<T> Reading<T> {
18 pub fn value(self) -> Option<T> {
19 match self {
20 Reading::Value(v) => Some(v),
21 Reading::Unavailable(_) => None,
22 }
23 }
24}
25
26#[derive(Clone, Copy, Debug, PartialEq)]
28pub enum Value {
29 Bool(bool),
30 U64(u64),
31 I64(i64),
32 F64(f64),
33 Flags(u64),
35 Fields(u64),
37 DateTime(i64),
39 Unavailable,
41}
42
43impl Value {
44 pub fn as_f64(self) -> Option<f64> {
45 match self {
46 Value::F64(v) => Some(v),
47 Value::U64(v) => Some(v as f64),
48 Value::I64(v) => Some(v as f64),
49 Value::Bool(b) => Some(if b { 1.0 } else { 0.0 }),
50 _ => None,
51 }
52 }
53
54 pub fn as_i64(self) -> Option<i64> {
55 match self {
56 Value::I64(v) => Some(v),
57 Value::U64(v) => i64::try_from(v).ok(),
58 Value::Bool(b) => Some(b as i64),
59 Value::F64(v) => Some(v as i64),
60 Value::Flags(m) => i64::try_from(m).ok(),
61 Value::Fields(w) => i64::try_from(w).ok(),
62 Value::DateTime(t) => Some(t),
63 Value::Unavailable => None,
64 }
65 }
66}
67
68impl From<f64> for Value {
69 fn from(v: f64) -> Self {
70 Value::F64(v)
71 }
72}
73
74impl From<i64> for Value {
75 fn from(v: i64) -> Self {
76 Value::I64(v)
77 }
78}
79
80impl From<u64> for Value {
81 fn from(v: u64) -> Self {
82 Value::U64(v)
83 }
84}
85
86impl From<bool> for Value {
87 fn from(v: bool) -> Self {
88 Value::Bool(v)
89 }
90}
91
92pub fn flag_names<'a>(desc: &PointDesc<'a>, mask: u64) -> impl Iterator<Item = &'a str> {
94 let table: &'a [(u8, &'a str)] = match desc.value {
95 ValueKind::Flags(t) => t,
96 _ => &[],
97 };
98 table
99 .iter()
100 .filter(move |(bit, _)| mask & (1u64 << bit) != 0)
101 .map(|(_, name)| *name)
102}
103
104pub fn field_value(f: &FieldDesc<'_>, window: u64) -> u64 {
106 let mask = if f.bit_length >= 64 {
107 u64::MAX
108 } else {
109 (1u64 << f.bit_length) - 1
110 };
111 (window >> f.bit_offset) & mask
112}
113
114#[cfg(feature = "alloc")]
116#[derive(Clone, Debug, PartialEq)]
117pub enum DecodedValue {
118 Bool(bool),
119 U64(u64),
120 I64(i64),
121 F64(f64),
122 Str(alloc::string::String),
123 Bytes(alloc::vec::Vec<u8>),
124 Flags(alloc::vec::Vec<alloc::string::String>),
126 Fields(alloc::vec::Vec<(alloc::string::String, u64)>),
128 DateTime(i64),
129 Unavailable(alloc::string::String),
130}
131
132#[cfg(feature = "alloc")]
133impl DecodedValue {
134 pub fn as_f64(&self) -> Option<f64> {
135 match self {
136 DecodedValue::F64(v) => Some(*v),
137 DecodedValue::U64(v) => Some(*v as f64),
138 DecodedValue::I64(v) => Some(*v as f64),
139 DecodedValue::Bool(b) => Some(if *b { 1.0 } else { 0.0 }),
140 _ => None,
141 }
142 }
143
144 pub fn as_i64(&self) -> Option<i64> {
145 match self {
146 DecodedValue::I64(v) => Some(*v),
147 DecodedValue::U64(v) => i64::try_from(*v).ok(),
148 DecodedValue::Bool(b) => Some(*b as i64),
149 DecodedValue::F64(v) => Some(*v as i64),
150 DecodedValue::DateTime(t) => Some(*t),
151 _ => None,
152 }
153 }
154
155 pub fn is_unavailable(&self) -> bool {
156 matches!(self, DecodedValue::Unavailable(_))
157 }
158}