melodium_common/executive/value/
mod.rs1mod data;
2mod packed;
3mod traits;
4
5use super::Data;
6use crate::descriptor::DataType;
7pub use data::GetData;
8pub use packed::PackedArray;
9use std::sync::Arc;
10
11#[derive(Clone, Debug)]
12pub enum Value {
13 Void(()),
14
15 I8(i8),
16 I16(i16),
17 I32(i32),
18 I64(i64),
19 I128(i128),
20
21 U8(u8),
22 U16(u16),
23 U32(u32),
24 U64(u64),
25 U128(u128),
26
27 F32(f32),
28 F64(f64),
29
30 Bool(bool),
31 Byte(u8),
32 Char(char),
33 String(String),
34
35 Vec(Vec<Value>),
36 Option(Option<Box<Value>>),
37 Packed(PackedArray),
41
42 Data(Arc<dyn Data>),
43}
44
45impl Value {
46 pub fn datatype(&self) -> DataType {
47 match self {
48 Value::Void(_) => DataType::Void,
49
50 Value::I8(_) => DataType::I8,
51 Value::I16(_) => DataType::I16,
52 Value::I32(_) => DataType::I32,
53 Value::I64(_) => DataType::I64,
54 Value::I128(_) => DataType::I128,
55
56 Value::U8(_) => DataType::U8,
57 Value::U16(_) => DataType::U16,
58 Value::U32(_) => DataType::U32,
59 Value::U64(_) => DataType::U64,
60 Value::U128(_) => DataType::U128,
61
62 Value::F32(_) => DataType::F32,
63 Value::F64(_) => DataType::F64,
64
65 Value::Bool(_) => DataType::Bool,
66 Value::Byte(_) => DataType::Byte,
67 Value::Char(_) => DataType::Char,
68 Value::String(_) => DataType::String,
69
70 Value::Option(val) => val
71 .as_ref()
72 .map(|val| DataType::Option(Box::new(val.datatype())))
73 .unwrap_or(DataType::Undetermined),
74 Value::Vec(val) => val
75 .first()
76 .map(|val| DataType::Vec(Box::new(val.datatype())))
77 .unwrap_or(DataType::Undetermined),
78 Value::Packed(arr) => DataType::Vec(Box::new(arr.element_datatype())),
79
80 Value::Data(obj) => DataType::Data(obj.descriptor()),
81 }
82 }
83
84 pub fn try_data<T>(self) -> Result<T, ()>
91 where
92 Self: GetData<T>,
93 {
94 GetData::<T>::try_data(self)
95 }
96
97 pub fn estimated_size(&self) -> usize {
106 const DATA_ESTIMATE: usize = 128;
107
108 std::mem::size_of::<Value>()
109 + match self {
110 Value::String(value) => value.len(),
111 Value::Vec(values) => values.iter().map(Value::estimated_size).sum(),
112 Value::Option(Some(value)) => value.estimated_size(),
113 Value::Packed(arr) => arr.estimated_size(),
114 Value::Data(_) => DATA_ESTIMATE,
115 _ => 0,
116 }
117 }
118}
119
120impl PartialEq for Value {
121 fn eq(&self, other: &Self) -> bool {
122 match (self, other) {
123 (Self::Void(l0), Self::Void(r0)) => l0 == r0,
124 (Self::I8(l0), Self::I8(r0)) => l0 == r0,
125 (Self::I16(l0), Self::I16(r0)) => l0 == r0,
126 (Self::I32(l0), Self::I32(r0)) => l0 == r0,
127 (Self::I64(l0), Self::I64(r0)) => l0 == r0,
128 (Self::I128(l0), Self::I128(r0)) => l0 == r0,
129 (Self::U8(l0), Self::U8(r0)) => l0 == r0,
130 (Self::U16(l0), Self::U16(r0)) => l0 == r0,
131 (Self::U32(l0), Self::U32(r0)) => l0 == r0,
132 (Self::U64(l0), Self::U64(r0)) => l0 == r0,
133 (Self::U128(l0), Self::U128(r0)) => l0 == r0,
134 (Self::F32(l0), Self::F32(r0)) => l0 == r0,
135 (Self::F64(l0), Self::F64(r0)) => l0 == r0,
136 (Self::Bool(l0), Self::Bool(r0)) => l0 == r0,
137 (Self::Byte(l0), Self::Byte(r0)) => l0 == r0,
138 (Self::Char(l0), Self::Char(r0)) => l0 == r0,
139 (Self::String(l0), Self::String(r0)) => l0 == r0,
140 (Self::Vec(l0), Self::Vec(r0)) => l0 == r0,
141 (Self::Option(l0), Self::Option(r0)) => l0 == r0,
142 (Self::Packed(l0), Self::Packed(r0)) => l0 == r0,
143 (Self::Data(l0), Self::Data(r0)) => {
144 if l0.descriptor() == r0.descriptor() {
145 if l0
146 .descriptor()
147 .implements()
148 .contains(&crate::descriptor::DataTrait::PartialEquality)
149 {
150 l0.partial_equality_eq(other)
151 } else {
152 false
153 }
154 } else {
155 false
156 }
157 }
158 _ => false,
159 }
160 }
161}
162
163#[cfg(test)]
164mod estimated_size_tests {
165 use super::Value;
166
167 #[test]
168 fn scalar_costs_only_the_enum_footprint() {
169 let base = std::mem::size_of::<Value>();
170 assert_eq!(Value::U64(42).estimated_size(), base);
171 assert_eq!(Value::Void(()).estimated_size(), base);
172 }
173
174 #[test]
175 fn string_costs_enum_footprint_plus_its_bytes() {
176 let base = std::mem::size_of::<Value>();
177 let text = "hello world".to_string();
178 let expected = base + text.len();
179 assert_eq!(Value::String(text).estimated_size(), expected);
180 }
181
182 #[test]
183 fn vec_sums_enum_footprint_of_every_element() {
184 let base = std::mem::size_of::<Value>();
185 let vec = Value::Vec(vec![Value::Byte(1), Value::Byte(2), Value::Byte(3)]);
186 assert_eq!(vec.estimated_size(), base + 3 * base);
189 }
190
191 #[test]
192 fn none_option_costs_only_the_enum_footprint() {
193 let base = std::mem::size_of::<Value>();
194 assert_eq!(Value::Option(None).estimated_size(), base);
195 }
196
197 #[test]
198 fn some_option_adds_the_inner_values_size() {
199 let base = std::mem::size_of::<Value>();
200 let text = "abcdef".to_string();
201 let inner_size = base + text.len();
202 let value = Value::Option(Some(Box::new(Value::String(text))));
203 assert_eq!(value.estimated_size(), base + inner_size);
204 }
205}