1use half::f16;
2use serde::{Serialize, Deserialize};
3use std::convert::{TryFrom, TryInto};
4
5#[derive(Debug, Clone, Copy, Serialize, Deserialize)]
28pub enum Value {
29 U8(u8),
31 U16(u16),
33 U32(u32),
35 U64(u64),
37 I8(i8),
39 I16(i16),
41 I32(i32),
43 I64(i64),
45 F16(f16),
47 F32(f32),
49 F64(f64),
51}
52
53#[derive(Debug, Clone, Copy, PartialEq, Eq, Serialize, Deserialize)]
57pub enum ValueType {
58 U8,
60 U16,
62 U32,
64 U64,
66 I8,
68 I16,
70 I32,
72 I64,
74 F16,
76 F32,
78 F64,
80}
81
82impl ValueType {
83 pub fn byte_length(&self) -> usize {
85 match self {
86 ValueType::U8 => 1,
87 ValueType::U16 => 2,
88 ValueType::U32 => 4,
89 ValueType::U64 => 8,
90 ValueType::I8 => 1,
91 ValueType::I16 => 2,
92 ValueType::I32 => 4,
93 ValueType::I64 => 8,
94 ValueType::F16 => 2,
95 ValueType::F32 => 4,
96 ValueType::F64 => 8,
97 }
98 }
99}
100
101impl From<Value> for ValueType {
102 fn from(value: Value) -> Self {
103 match value {
104 Value::U8(_) => ValueType::U8,
105 Value::U16(_) => ValueType::U16,
106 Value::U32(_) => ValueType::U32,
107 Value::U64(_) => ValueType::U64,
108 Value::I8(_) => ValueType::I8,
109 Value::I16(_) => ValueType::I16,
110 Value::I32(_) => ValueType::I32,
111 Value::I64(_) => ValueType::I64,
112 Value::F16(_) => ValueType::F16,
113 Value::F32(_) => ValueType::F32,
114 Value::F64(_) => ValueType::F64,
115 }
116 }
117}
118
119macro_rules! primitive_impl {
122 ($ty:ident, $name:ident) => {
123 impl From<$ty> for Value {
124 fn from(v: $ty) -> Self {
125 Value::$name(v)
126 }
127 }
128
129 impl TryFrom<Value> for $ty {
130 type Error = crate::Error;
131
132 fn try_from(value: Value) -> Result<$ty, Self::Error> {
133 match value {
134 Value::$name(v) => Ok(v),
135 _ => Err(Self::Error::ConversionError(format!(
136 "Cannot convert {:?} to {}",
137 value,
138 stringify!($ty)
139 ))),
140 }
141 }
142 }
143 };
144}
145
146primitive_impl!(u8, U8);
147primitive_impl!(u16, U16);
148primitive_impl!(u32, U32);
149primitive_impl!(u64, U64);
150primitive_impl!(i8, I8);
151primitive_impl!(i16, I16);
152primitive_impl!(i32, I32);
153primitive_impl!(i64, I64);
154primitive_impl!(f16, F16);
155primitive_impl!(f32, F32);
156primitive_impl!(f64, F64);
157
158impl Value {
160 pub fn from_le_bytes(bytes: &[u8], value_type: ValueType) -> Result<Value, crate::Error> {
163 match value_type {
164 ValueType::U8 => Ok(Value::U8(u8::from_le_bytes(bytes.try_into()?))),
165 ValueType::U16 => Ok(Value::U16(u16::from_le_bytes(bytes.try_into()?))),
166 ValueType::U32 => Ok(Value::U32(u32::from_le_bytes(bytes.try_into()?))),
167 ValueType::U64 => Ok(Value::U64(u64::from_le_bytes(bytes.try_into()?))),
168 ValueType::I8 => Ok(Value::I8(i8::from_le_bytes(bytes.try_into()?))),
169 ValueType::I16 => Ok(Value::I16(i16::from_le_bytes(bytes.try_into()?))),
170 ValueType::I32 => Ok(Value::I32(i32::from_le_bytes(bytes.try_into()?))),
171 ValueType::I64 => Ok(Value::I64(i64::from_le_bytes(bytes.try_into()?))),
172 ValueType::F16 => Ok(Value::F16(f16::from_le_bytes(bytes.try_into()?))),
173 ValueType::F32 => Ok(Value::F32(f32::from_le_bytes(bytes.try_into()?))),
174 ValueType::F64 => Ok(Value::F64(f64::from_le_bytes(bytes.try_into()?))),
175 }
176 }
177
178 pub fn to_f64_lossy(&self) -> f64 {
183 match *self {
184 Value::U8(v) => v as f64,
185 Value::U16(v) => v as f64,
186 Value::U32(v) => v as f64,
187 Value::U64(v) => v as f64,
188 Value::I8(v) => v as f64,
189 Value::I16(v) => v as f64,
190 Value::I32(v) => v as f64,
191 Value::I64(v) => v as f64,
192 Value::F16(v) => v.to_f64(),
193 Value::F32(v) => v as f64,
194 Value::F64(v) => v as f64,
195 }
196 }
197
198 pub fn from_f64_lossy(value_type: ValueType, value: f64) -> Value {
209 match value_type {
210 ValueType::U8 => Value::U8((value as u64) as u8),
211 ValueType::U16 => Value::U16((value as u64) as u16),
212 ValueType::U32 => Value::U32((value as u64) as u32),
213 ValueType::U64 => Value::U64((value as u64) as u64),
214 ValueType::I8 => Value::I8((value as i64) as i8),
215 ValueType::I16 => Value::I16((value as i64) as i16),
216 ValueType::I32 => Value::I32((value as i64) as i32),
217 ValueType::I64 => Value::I64((value as i64) as i64),
218 ValueType::F16 => Value::F16(f16::from_f64(value)),
219 ValueType::F32 => Value::F32(value as f32),
220 ValueType::F64 => Value::F64(value),
221 }
222 }
223}
224
225impl From<Value> for Vec<u8> {
226 fn from(value: Value) -> Self {
227 match value {
228 Value::U8(v) => v.to_le_bytes().into(),
229 Value::U16(v) => v.to_le_bytes().into(),
230 Value::U32(v) => v.to_le_bytes().into(),
231 Value::U64(v) => v.to_le_bytes().into(),
232 Value::I8(v) => v.to_le_bytes().into(),
233 Value::I16(v) => v.to_le_bytes().into(),
234 Value::I32(v) => v.to_le_bytes().into(),
235 Value::I64(v) => v.to_le_bytes().into(),
236 Value::F16(v) => v.to_le_bytes().into(),
237 Value::F32(v) => v.to_le_bytes().into(),
238 Value::F64(v) => v.to_le_bytes().into(),
239 }
240 }
241}