1use half::f16;
2use std::convert::{TryFrom, TryInto};
3
4#[derive(Debug, Clone, Copy)]
27pub enum Value {
28 U8(u8),
30 U16(u16),
32 U32(u32),
34 U64(u64),
36 I8(i8),
38 I16(i16),
40 I32(i32),
42 I64(i64),
44 F16(f16),
46 F32(f32),
48 F64(f64),
50}
51
52#[derive(Debug, Clone, Copy, PartialEq, Eq)]
56pub enum ValueType {
57 U8,
59 U16,
61 U32,
63 U64,
65 I8,
67 I16,
69 I32,
71 I64,
73 F16,
75 F32,
77 F64,
79}
80
81impl ValueType {
82 pub fn byte_length(&self) -> usize {
84 match self {
85 ValueType::U8 => 1,
86 ValueType::U16 => 2,
87 ValueType::U32 => 4,
88 ValueType::U64 => 8,
89 ValueType::I8 => 1,
90 ValueType::I16 => 2,
91 ValueType::I32 => 4,
92 ValueType::I64 => 8,
93 ValueType::F16 => 2,
94 ValueType::F32 => 4,
95 ValueType::F64 => 8,
96 }
97 }
98}
99
100impl From<Value> for ValueType {
101 fn from(value: Value) -> Self {
102 match value {
103 Value::U8(_) => ValueType::U8,
104 Value::U16(_) => ValueType::U16,
105 Value::U32(_) => ValueType::U32,
106 Value::U64(_) => ValueType::U64,
107 Value::I8(_) => ValueType::I8,
108 Value::I16(_) => ValueType::I16,
109 Value::I32(_) => ValueType::I32,
110 Value::I64(_) => ValueType::I64,
111 Value::F16(_) => ValueType::F16,
112 Value::F32(_) => ValueType::F32,
113 Value::F64(_) => ValueType::F64,
114 }
115 }
116}
117
118macro_rules! primitive_impl {
121 ($ty:ident, $name:ident) => {
122 impl From<$ty> for Value {
123 fn from(v: $ty) -> Self {
124 Value::$name(v)
125 }
126 }
127
128 impl TryFrom<Value> for $ty {
129 type Error = crate::Error;
130
131 fn try_from(value: Value) -> Result<$ty, Self::Error> {
132 match value {
133 Value::$name(v) => Ok(v),
134 _ => Err(Self::Error::ConversionError(format!(
135 "Cannot convert {:?} to {}",
136 value,
137 stringify!($ty)
138 ))),
139 }
140 }
141 }
142 };
143}
144
145primitive_impl!(u8, U8);
146primitive_impl!(u16, U16);
147primitive_impl!(u32, U32);
148primitive_impl!(u64, U64);
149primitive_impl!(i8, I8);
150primitive_impl!(i16, I16);
151primitive_impl!(i32, I32);
152primitive_impl!(i64, I64);
153primitive_impl!(f16, F16);
154primitive_impl!(f32, F32);
155primitive_impl!(f64, F64);
156
157impl Value {
159 pub fn from_le_bytes(bytes: &[u8], value_type: ValueType) -> Result<Value, crate::Error> {
162 match value_type {
163 ValueType::U8 => Ok(Value::U8(u8::from_le_bytes(bytes.try_into()?))),
164 ValueType::U16 => Ok(Value::U16(u16::from_le_bytes(bytes.try_into()?))),
165 ValueType::U32 => Ok(Value::U32(u32::from_le_bytes(bytes.try_into()?))),
166 ValueType::U64 => Ok(Value::U64(u64::from_le_bytes(bytes.try_into()?))),
167 ValueType::I8 => Ok(Value::I8(i8::from_le_bytes(bytes.try_into()?))),
168 ValueType::I16 => Ok(Value::I16(i16::from_le_bytes(bytes.try_into()?))),
169 ValueType::I32 => Ok(Value::I32(i32::from_le_bytes(bytes.try_into()?))),
170 ValueType::I64 => Ok(Value::I64(i64::from_le_bytes(bytes.try_into()?))),
171 ValueType::F16 => Ok(Value::F16(f16::from_le_bytes(bytes.try_into()?))),
172 ValueType::F32 => Ok(Value::F32(f32::from_le_bytes(bytes.try_into()?))),
173 ValueType::F64 => Ok(Value::F64(f64::from_le_bytes(bytes.try_into()?))),
174 }
175 }
176
177 pub fn to_f64_lossy(&self) -> f64 {
182 match *self {
183 Value::U8(v) => v as f64,
184 Value::U16(v) => v as f64,
185 Value::U32(v) => v as f64,
186 Value::U64(v) => v as f64,
187 Value::I8(v) => v as f64,
188 Value::I16(v) => v as f64,
189 Value::I32(v) => v as f64,
190 Value::I64(v) => v as f64,
191 Value::F16(v) => v.to_f64(),
192 Value::F32(v) => v as f64,
193 Value::F64(v) => v as f64,
194 }
195 }
196
197 pub fn from_f64_lossy(value_type: ValueType, value: f64) -> Value {
208 match value_type {
209 ValueType::U8 => Value::U8((value as u64) as u8),
210 ValueType::U16 => Value::U16((value as u64) as u16),
211 ValueType::U32 => Value::U32((value as u64) as u32),
212 ValueType::U64 => Value::U64((value as u64) as u64),
213 ValueType::I8 => Value::I8((value as i64) as i8),
214 ValueType::I16 => Value::I16((value as i64) as i16),
215 ValueType::I32 => Value::I32((value as i64) as i32),
216 ValueType::I64 => Value::I64((value as i64) as i64),
217 ValueType::F16 => Value::F16(f16::from_f64(value)),
218 ValueType::F32 => Value::F32(value as f32),
219 ValueType::F64 => Value::F64(value),
220 }
221 }
222}
223
224impl From<Value> for Vec<u8> {
225 fn from(value: Value) -> Self {
226 match value {
227 Value::U8(v) => v.to_le_bytes().into(),
228 Value::U16(v) => v.to_le_bytes().into(),
229 Value::U32(v) => v.to_le_bytes().into(),
230 Value::U64(v) => v.to_le_bytes().into(),
231 Value::I8(v) => v.to_le_bytes().into(),
232 Value::I16(v) => v.to_le_bytes().into(),
233 Value::I32(v) => v.to_le_bytes().into(),
234 Value::I64(v) => v.to_le_bytes().into(),
235 Value::F16(v) => v.to_le_bytes().into(),
236 Value::F32(v) => v.to_le_bytes().into(),
237 Value::F64(v) => v.to_le_bytes().into(),
238 }
239 }
240}