1use crate::matrix::Matrix;
2use crate::*;
3use crate::nodes::Matrix as Mat;
4use crate::{MechError, MechErrorKind, hash_str, nodes::Kind as NodeKind, nodes::*, humanize};
5use std::collections::HashMap;
6
7use na::{Vector3, DVector, Vector2, Vector4, RowDVector, Matrix1, Matrix3, Matrix4, RowVector3, RowVector4, RowVector2, DMatrix, Rotation3, Matrix2x3, Matrix3x2, Matrix6, Matrix2};
8use std::hash::{Hash, Hasher};
9use indexmap::set::IndexSet;
10use indexmap::map::*;
11use tabled::{
12 builder::Builder,
13 settings::{object::Rows,Panel, Span, Alignment, Modify, Style},
14 Tabled,
15};
16use paste::paste;
17use serde::ser::{Serialize, Serializer, SerializeStruct};
18use serde::de::{self, Deserialize, SeqAccess, Deserializer, MapAccess, Visitor};
19use std::fmt;
20use std::cell::RefCell;
21use std::rc::Rc;
22
23#[derive(Clone, Debug, PartialEq, Eq)]
26pub struct MechSet {
27 pub kind: ValueKind,
28 pub num_elements: usize,
29 pub set: IndexSet<Value>,
30}
31
32impl MechSet {
33
34 pub fn to_html(&self) -> String {
35 let mut src = String::new();
36 for (i, element) in self.set.iter().enumerate() {
37 let e = element.to_html();
38 if i == 0 {
39 src = format!("{}", e);
40 } else {
41 src = format!("{}, {}", src, e);
42 }
43 }
44 format!("<span class=\"mech-set\"><span class=\"mech-start-brace\">{{</span>{}<span class=\"mech-end-brace\">}}</span></span>",src)
45 }
46
47 pub fn kind(&self) -> ValueKind {
48 let size = if self.num_elements > 0 { Some(self.num_elements) } else { None };
49 ValueKind::Set(Box::new(self.kind.clone()), size)
50 }
51
52 pub fn size_of(&self) -> usize {
53 self.set.iter().map(|x| x.size_of()).sum()
54 }
55
56 pub fn from_vec(vec: Vec<Value>) -> MechSet {
57 let mut set = IndexSet::new();
58 for v in vec {
59 set.insert(v);
60 }
61 let kind = if set.len() > 0 { set.iter().next().unwrap().kind() } else { ValueKind::Empty };
62 MechSet{
63 kind,
64 num_elements: set.len(),
65 set}
66 }
67
68 pub fn pretty_print(&self) -> String {
69 let mut builder = Builder::default();
70 let mut element_strings = vec![];
71 for x in self.set.iter() {
72 element_strings.push(x.pretty_print());
73 }
74 builder.push_record(element_strings);
75
76 let style = Style::empty()
77 .top(' ')
78 .left('║')
79 .right('║')
80 .bottom(' ')
81 .vertical(' ')
82 .intersection_bottom(' ')
83 .corner_top_left('╔')
84 .corner_top_right('╗')
85 .corner_bottom_left('╚')
86 .corner_bottom_right('╝');
87 let mut table = builder.build();
88 table.with(style);
89 format!("{table}")
90 }
91
92}
93
94impl Hash for MechSet {
95 fn hash<H: Hasher>(&self, state: &mut H) {
96 for x in self.set.iter() {
97 x.hash(state)
98 }
99 }
100}
101
102#[derive(Clone, Debug, PartialEq, Eq)]
105pub struct MechMap {
106 pub key_kind: ValueKind,
107 pub value_kind: ValueKind,
108 pub num_elements: usize,
109 pub map: IndexMap<Value,Value>,
110}
111
112impl MechMap {
113
114 pub fn to_html(&self) -> String {
115 let mut src = String::new();
116 for (i, (key, value)) in self.map.iter().enumerate() {
117 let k = key.to_html();
118 let v = value.to_html();
119 if i == 0 {
120 src = format!("{}: {}", k, v);
121 } else {
122 src = format!("{}, {}: {}", src, k, v);
123 }
124 }
125 format!("<span class=\"mech-map\"><span class=\"mech-start-brace\">{{</span>{}<span class=\"mech-end-brace\">}}</span></span>",src)
126 }
127
128 pub fn kind(&self) -> ValueKind {
129 ValueKind::Map(Box::new(self.key_kind.clone()), Box::new(self.value_kind.clone()))
130 }
131
132 pub fn size_of(&self) -> usize {
133 self.map.iter().map(|(k,v)| k.size_of() + v.size_of()).sum()
134 }
135
136 pub fn pretty_print(&self) -> String {
137 let mut builder = Builder::default();
138 let mut element_strings = vec![];
139 let mut key_strings = vec![];
140 for (k,v) in self.map.iter() {
141 element_strings.push(v.pretty_print());
142 key_strings.push(k.pretty_print());
143 }
144 builder.push_record(key_strings);
145 builder.push_record(element_strings);
146 let mut table = builder.build();
147 table.with(Style::modern_rounded());
148 format!("{table}")
149 }
150
151 pub fn from_vec(vec: Vec<(Value,Value)>) -> MechMap {
152 let mut map = IndexMap::new();
153 for (k,v) in vec {
154 map.insert(k,v);
155 }
156 MechMap{
157 key_kind: map.keys().next().unwrap().kind(),
158 value_kind: map.values().next().unwrap().kind(),
159 num_elements: map.len(),
160 map}
161 }
162}
163
164impl Hash for MechMap {
165 fn hash<H: Hasher>(&self, state: &mut H) {
166 for x in self.map.iter() {
167 x.hash(state)
168 }
169 }
170}
171
172#[derive(Clone, Debug, PartialEq, Eq)]
175pub struct MechTable {
176 pub rows: usize,
177 pub cols: usize,
178 pub data: IndexMap<u64,(ValueKind,Matrix<Value>)>,
179 pub col_names: HashMap<u64,String>,
180}
181
182impl MechTable {
183
184 pub fn from_records(records: Vec<MechRecord>) -> MResult<MechTable> {
185 if records.is_empty() {
186 return Err(MechError { id: line!(), file: file!().to_string(), tokens: vec![], msg: "Cannot create MechTable from empty record list.".to_string(), kind: MechErrorKind::None});
187 }
188
189 let first = &records[0];
190 let rows = records.len();
191 let cols = first.cols;
192
193 let mut col_data: IndexMap<u64, Vec<Value>> = IndexMap::new();
194
195 for (&col_id, value) in &first.data {
196 col_data.insert(col_id, vec![value.clone()]);
197 }
198
199 let mut kinds = IndexMap::new();
200 for (col_id, kind) in first.data.keys().zip(&first.kinds) {
201 kinds.insert(*col_id, kind.clone());
202 }
203
204 let col_names = first.field_names.clone();
205
206 for record in records.iter().skip(1) {
207 first.check_record_schema(record)?;
208 for (&col_id, value) in &record.data {
209 col_data.entry(col_id).or_insert_with(Vec::new).push(value.clone());
210 }
211 }
212
213 let data: IndexMap<u64, (ValueKind, Matrix<Value>)> = col_data
214 .into_iter()
215 .map(|(col_id, values)| {
216 let kind = kinds[&col_id].clone();
217 let matrix = Matrix::DVector(new_ref(DVector::from_vec(values)));
218 (col_id, (kind, matrix))
219 })
220 .collect();
221
222 Ok(MechTable {rows,cols,data,col_names})
223 }
224
225 pub fn from_kind(kind: ValueKind) -> MResult<MechTable> {
226 match kind {
227 ValueKind::Table(tbl,sze) => {
228 let mut data = IndexMap::new();
229 let mut col_names = HashMap::new();
230 for (col_id, col_kind) in &tbl {
231 let matrix = Matrix::DVector(new_ref(DVector::from_vec(vec![Value::Empty; sze])));
232 col_names.insert(hash_str(col_id), col_id.clone());
233 data.insert(hash_str(&col_id), (col_kind.clone(), matrix));
234 }
235 Ok(MechTable {rows: sze, cols: tbl.len(), data, col_names})
236 }
237 _ => {
238 return Err(MechError { id: line!(), file: file!().to_string(), tokens: vec![], msg: "Cannot create MechTable from non-table kind.".to_string(), kind: MechErrorKind::None });
239 }
240 }
241 }
242
243 pub fn empty_table(&self, rows: usize) -> MechTable {
244 let mut data = IndexMap::new();
245 for col in self.data.iter() {
246 let (key, (kind, matrix)) = col;
247 let elements = vec![Value::Empty; rows];
249 let new_matrix = Matrix::DVector(new_ref(DVector::from_vec(elements)));
250 data.insert(*key, (kind.clone(), new_matrix));
251 }
252 MechTable { rows: rows, cols: self.cols, data, col_names: self.col_names.clone() }
253 }
254
255 pub fn check_record_schema(&self, record: &MechRecord) -> MResult<bool> {
256
257 for (&col_id, record_value) in &record.data {
258 let (expected_kind, column_matrix) = match self.data.get(&col_id) {
261 Some(data) => data,
262 None => {
263 continue;
264 }
265 };
266
267 let actual_kind = record_value.kind();
269
270 if expected_kind != &actual_kind {
271 return Err(MechError {id: line!(),file: file!().to_string(),tokens: vec![],msg: format!("Schema mismatch: column {} kind mismatch (expected: {:?}, found: {:?})",col_id, expected_kind, actual_kind),kind: MechErrorKind::None,});
272 }
273
274 if let Some(expected_name) = self.col_names.get(&col_id) {
276 if let Some(field_name) = record.field_names.get(&col_id) {
277 if expected_name != field_name {
278 return Err(MechError {id: line!(),file: file!().to_string(),tokens: vec![],msg: format!("Schema mismatch: column {} name mismatch (expected: '{}', found: '{}')",col_id, expected_name, field_name),kind: MechErrorKind::None,});
279 }
280 }
281 }
282 }
283
284 Ok(true)
285 }
286
287 pub fn check_table_schema(&self, record: &MechTable) -> MResult<bool> {
288
289 for (&col_id, col_name) in &self.col_names {
291 if let Some(record_name) = record.col_names.get(&col_id) {
292 if col_name != record_name {
293 return Err(MechError {id: line!(),file: file!().to_string(),tokens: vec![],msg: format!("Schema mismatch: column {} name mismatch (expected: '{}', found: '{}')",col_id, col_name, record_name),kind: MechErrorKind::None,});
294 }
295 } else {
296 return Err(MechError {id: line!(),file: file!().to_string(),tokens: vec![],msg: format!("Schema mismatch: column {} not found in record",col_id),kind: MechErrorKind::None,});
297 }
298 }
299
300 for (&col_id, (expected_kind, _)) in &self.data {
302 if let Some((record_kind, _)) = record.data.get(&col_id) {
303 if expected_kind != record_kind {
304 return Err(MechError {id: line!(),file: file!().to_string(),tokens: vec![],msg: format!("Schema mismatch: column {} kind mismatch (expected: {:?}, found: {:?})",col_id, expected_kind, record_kind),kind: MechErrorKind::None,});
305 }
306 } else {
307 return Err(MechError {id: line!(),file: file!().to_string(),tokens: vec![],msg: format!("Schema mismatch: column {} not found in record",col_id),kind: MechErrorKind::None,});
308 }
309 }
310
311 Ok(true)
312 }
313
314 pub fn append_table(&mut self, other: &MechTable) -> MResult<()> {
315 self.check_table_schema(other)?;
316 for (&col_id, (_, other_matrix)) in &other.data {
317 let (_, self_matrix) = self.data.get_mut(&col_id).ok_or(MechError {
318 id: line!(),
319 file: file!().to_string(),
320 tokens: vec![],
321 msg: format!("Column {} not found in destination table", col_id),
322 kind: MechErrorKind::None,
323 })?;
324
325 self_matrix.append(other_matrix).map_err(|err| MechError {
326 id: line!(),
327 file: file!().to_string(),
328 tokens: vec![],
329 msg: "".to_string(),
330 kind: MechErrorKind::None,
331 })?;
332 }
333 self.rows += other.rows;
334 Ok(())
335 }
336
337 pub fn append_record(&mut self, record: MechRecord) -> MResult<()> {
338 self.check_record_schema(&record)?;
340
341 for (&col_id, value) in &record.data {
343 if let Some((_kind, column_matrix)) = self.data.get_mut(&col_id) {
344 let result = column_matrix.push(value.clone());
345 } else {
346 continue;
347 }
348 }
349
350 self.rows += 1;
352
353 Ok(())
354 }
355
356 pub fn get_record(&self, ix: usize) -> Option<MechRecord> {
357 if ix > self.rows {
358 return None;
359 }
360
361 let mut data: IndexMap<u64, Value> = IndexMap::new();
362 data = self.data.iter().map(|(key, (kind, matrix))| {
363 let value = matrix.index1d(ix);
364 let name = self.col_names.get(key).unwrap();
365 (hash_str(name), value.clone())
366 }).collect();
367
368 let mut kinds = Vec::with_capacity(self.cols);
369 kinds = self.data.iter().map(|(_, (kind, _))| kind.clone()).collect();
370
371 let mut field_names = self.col_names.clone();
372
373 Some(MechRecord{cols: self.cols, kinds, data, field_names})
374 }
375
376
377 pub fn to_html(&self) -> String {
378 let mut html = String::new();
379
380 html.push_str("<table class=\"mech-table\">");
382
383 html.push_str("<thead class=\"mech-table-header\"><tr>");
385 for (key, (kind, _matrix)) in self.data.iter() {
386 let col_name = self
387 .col_names
388 .get(key)
389 .cloned()
390 .unwrap_or_else(|| key.to_string());
391
392 let kind_str = format!(
393 "<span class=\"mech-kind-annotation\"><<span class=\"mech-kind\">{}</span>></span>",
394 kind
395 );
396
397 html.push_str(&format!(
398 "<th class=\"mech-table-field\">\
399 <div class=\"mech-field\">\
400 <span class=\"mech-field-name\">{}</span>\
401 <span class=\"mech-field-kind\">{}</span>\
402 </div>\
403 </th>",
404 col_name, kind_str
405 ));
406 }
407 html.push_str("</tr></thead>");
408
409 html.push_str("<tbody class=\"mech-table-body\">");
411 for row_idx in 1..=self.rows {
412 html.push_str("<tr class=\"mech-table-row\">");
413 for (_key, (_kind, matrix)) in self.data.iter() {
414 let value = matrix.index1d(row_idx);
415 html.push_str(&format!(
416 "<td class=\"mech-table-column\">{}</td>",
417 value.to_html()
418 ));
419 }
420 html.push_str("</tr>");
421 }
422 html.push_str("</tbody></table>");
423 html
424 }
425
426 pub fn new(rows: usize, cols: usize, data: IndexMap<u64,(ValueKind,Matrix<Value>)>, col_names: HashMap<u64,String>) -> MechTable {
427 MechTable{rows, cols, data, col_names}
428 }
429
430 pub fn kind(&self) -> ValueKind {
431 let column_kinds: Vec<(String, ValueKind)> = self.data.iter()
432 .filter_map(|(key, (kind, _))| {
433 let col_name = self.col_names.get(key)?;
434 Some((col_name.clone(), kind.clone()))
435 })
436 .collect();
437 ValueKind::Table(column_kinds, self.rows)
438 }
439
440 pub fn size_of(&self) -> usize {
441 self.data.iter().map(|(_,(_,v))| v.size_of()).sum()
442 }
443
444 pub fn rows(&self) -> usize {
445 self.rows
446 }
447
448 pub fn cols(&self) -> usize {
449 self.cols
450 }
451
452 pub fn get(&self, key: &u64) -> Option<&(ValueKind,Matrix<Value>)> {
453 self.data.get(key)
454 }
455
456 pub fn pretty_print(&self) -> String {
457 let mut builder = Builder::default();
458 for (k,(knd,val)) in &self.data {
459 let name = self.col_names.get(k).unwrap();
460 let val_string: String = val.as_vec().iter()
461 .map(|x| x.pretty_print())
462 .collect::<Vec<String>>()
463 .join("\n");
464 let mut col_string = vec![format!("{}<{}>", name.to_string(), knd), val_string];
465 builder.push_column(col_string);
466 }
467 let mut table = builder.build();
468 table.with(Style::modern_rounded());
469 format!("{table}")
470 }
471
472 pub fn shape(&self) -> Vec<usize> {
473 vec![self.rows,self.cols]
474 }
475}
476
477impl Hash for MechTable {
478 fn hash<H: Hasher>(&self, state: &mut H) {
479 for (k,(knd,val)) in self.data.iter() {
480 k.hash(state);
481 knd.hash(state);
482 val.hash(state);
483 }
484 }
485}
486
487#[derive(Clone, Debug, PartialEq, Eq)]
490pub struct MechRecord {
491 pub cols: usize,
492 pub kinds: Vec<ValueKind>,
493 pub data: IndexMap<u64,Value>,
494 pub field_names: HashMap<u64,String>,
495}
496
497impl MechRecord {
498
499 pub fn check_record_schema(&self, record: &MechRecord) -> MResult<()> {
500 for (&col_id, _value) in &self.data {
501 if !record.data.contains_key(&col_id) {
503 return Err(MechError {id: line!(),file: file!().to_string(),tokens: vec![],msg: format!("Missing column {} in record data", col_id),kind: MechErrorKind::None});
504 }
505
506 let expected_kind = self.kinds.get(self.key_index(col_id)?).ok_or_else(|| MechError { id: line!(), file: file!().to_string(), tokens: vec![], msg: format!("Missing kind for column {}", col_id), kind: MechErrorKind::None})?;
508
509 let actual_kind = record.kinds.get(record.key_index(col_id)?).ok_or_else(|| MechError {id: line!(),file: file!().to_string(),tokens: vec![],msg: format!("Missing kind for column {} in compared record", col_id),kind: MechErrorKind::None,})?;
511
512 if expected_kind != actual_kind {
514 return Err(MechError {id: line!(),file: file!().to_string(),tokens: vec![],msg: format!("Kind mismatch for column {} (expected {:?}, found {:?})", col_id, expected_kind, actual_kind),kind: MechErrorKind::None,});
515 }
516
517 let expected_name = self.field_names.get(&col_id);
519 let actual_name = record.field_names.get(&col_id);
520
521 if expected_name != actual_name {
522 return Err(MechError {id: line!(),file: file!().to_string(),tokens: vec![],msg: "".to_string(),kind: MechErrorKind::None,});
523 }
524 }
525
526 Ok(())
527 }
528
529 fn key_index(&self, col_id: u64) -> MResult<usize> {
530 self.data.keys().position(|&id| id == col_id).ok_or_else(|| MechError {
531 id: line!(),
532 file: file!().to_string(),
533 tokens: vec![],
534 msg: format!("Column id {} not found in key_index", col_id),
535 kind: MechErrorKind::None,
536 })
537 }
538
539 pub fn to_html(&self) -> String {
540 let mut bindings = Vec::new();
541
542 for (key, value) in &self.data {
543 let name = self.field_names.get(key).unwrap();
544
545 let binding_html = format!(
546 "<span class=\"mech-binding\">\
547 <span class=\"mech-binding-name\">{}</span>\
548 <span class=\"mech-binding-colon-op\">:</span>\
549 <span class=\"mech-binding-value\">{}</span>\
550 </span>",
551 name,
552 value.to_html(),
553 );
554
555 bindings.push(binding_html);
556 }
557
558 format!(
559 "<span class=\"mech-record\">\
560 <span class=\"mech-start-brace\">{{</span>{}<span class=\"mech-end-brace\">}}</span>\
561 </span>",
562 bindings.join("<span class=\"mech-separator\">, </span>")
563 )
564 }
565
566 pub fn get(&self, key: &u64) -> Option<&Value> {
567 self.data.get(key)
568 }
569
570 pub fn new(vec: Vec<(&str, Value)>) -> MechRecord {
571 use std::collections::hash_map::DefaultHasher;
572 use std::hash::{Hash, Hasher};
573
574 let mut data = IndexMap::new();
575 let mut field_names = HashMap::new();
576
577 for (name, value) in vec {
578 let col_id = hash_str(name);
579
580 field_names.insert(col_id, name.to_string());
581 data.insert(col_id, value);
582 }
583
584 let kinds = data.iter().map(|(_, v)| v.kind()).collect();
585
586 MechRecord {
587 cols: data.len(),
588 kinds,
589 data,
590 field_names,
591 }
592 }
593
594 pub fn from_vec(vec: Vec<((u64,String),Value)>) -> MechRecord {
595 let mut data = IndexMap::new();
596 let mut field_names = HashMap::new();
597 for ((k,s),v) in vec {
598 field_names.insert(k,s);
599 data.insert(k,v);
600 }
601 let kinds = data.iter().map(|(_,v)| v.kind()).collect();
602 MechRecord{cols: data.len(), kinds, data, field_names}
603 }
604
605 pub fn insert_field(&mut self, key: u64, value: Value) {
606 self.cols += 1;
607 self.kinds.push(value.kind());
608 self.data.insert(key, value);
609 }
610
611 pub fn kind(&self) -> ValueKind {
612 ValueKind::Record(self.data.iter()
613 .map(|(k,v)| (self.field_names.get(k).unwrap().to_string(), v.kind()))
614 .collect())
615 }
616
617 pub fn size_of(&self) -> usize {
618 self.data.iter().map(|(_,v)| v.size_of()).sum()
619 }
620
621 pub fn pretty_print(&self) -> String {
622 let mut builder = Builder::default();
623 let mut key_strings = vec![];
624 let mut element_strings = vec![];
625 for (k,v) in &self.data {
626 let field_name = self.field_names.get(k).unwrap();
627 key_strings.push(format!("{}<{}>",field_name, v.kind()));
628 element_strings.push(v.pretty_print());
629 }
630 builder.push_record(key_strings);
631 builder.push_record(element_strings);
632 let mut table = builder.build();
633 table.with(Style::modern_rounded());
634 format!("{table}")
635 }
636
637 pub fn shape(&self) -> Vec<usize> {
638 vec![1,self.cols]
639 }
640}
641
642impl Hash for MechRecord {
643 fn hash<H: Hasher>(&self, state: &mut H) {
644 for (k,v) in self.data.iter() {
645 k.hash(state);
646 v.hash(state);
647 }
648 }
649}
650
651#[derive(Clone, Debug, PartialEq, Eq)]
654pub struct MechTuple {
655 pub elements: Vec<Box<Value>>
656}
657
658impl MechTuple {
659
660 pub fn to_html(&self) -> String {
661 let mut elements = Vec::new();
662 for element in &self.elements {
663 elements.push(element.to_html());
664 }
665 format!("<span class=\"mech-tuple\"><span class=\"mech-start-brace\">(</span>{}<span class=\"mech-end-brace\">)</span></span>", elements.join(", "))
666 }
667
668 pub fn pretty_print(&self) -> String {
669 let mut builder = Builder::default();
670 let string_elements: Vec<String> = self.elements.iter().map(|e| e.pretty_print()).collect::<Vec<String>>();
671 builder.push_record(string_elements);
672 let mut table = builder.build();
673 let style = Style::empty()
674 .top(' ')
675 .left('│')
676 .right('│')
677 .bottom(' ')
678 .vertical(' ')
679 .intersection_bottom('ʼ')
680 .corner_top_left('╭')
681 .corner_top_right('╮')
682 .corner_bottom_left('╰')
683 .corner_bottom_right('╯');
684 table.with(style);
685 format!("{table}")
686 }
687
688 pub fn get(&self, index: usize) -> Option<&Value> {
689 if index < self.elements.len() {
690 Some(self.elements[index].as_ref())
691 } else {
692 None
693 }
694 }
695
696 pub fn from_vec(elements: Vec<Value>) -> Self {
697 MechTuple{elements: elements.iter().map(|m| Box::new(m.clone())).collect::<Vec<Box<Value>>>()}
698 }
699
700 pub fn size(&self) -> usize {
701 self.elements.len()
702 }
703
704 pub fn kind(&self) -> ValueKind {
705 ValueKind::Tuple(self.elements.iter().map(|x| x.kind()).collect())
706 }
707
708 pub fn size_of(&self) -> usize {
709 self.elements.iter().map(|x| x.size_of()).sum()
710 }
711
712}
713
714impl Hash for MechTuple {
715 fn hash<H: Hasher>(&self, state: &mut H) {
716 for x in self.elements.iter() {
717 x.hash(state)
718 }
719 }
720}
721
722#[derive(Clone, Debug, PartialEq, Eq)]
725pub struct MechEnum {
726 pub id: u64,
727 pub variants: Vec<(u64, Option<Value>)>,
728}
729
730impl MechEnum {
731
732 pub fn to_html(&self) -> String {
733 let mut variants = Vec::new();
734 for (id, value) in &self.variants {
735 let value_html = match value {
736 Some(v) => v.to_html(),
737 None => "None".to_string(),
738 };
739 variants.push(format!("<span class=\"mech-enum-variant\">{}: {}</span>", id, value_html));
740 }
741 format!("<span class=\"mech-enum\"><span class=\"mech-start-brace\">{{</span>{}<span class=\"mech-end-brace\">}}</span></span>", variants.join(", "))
742 }
743
744 pub fn kind(&self) -> ValueKind {
745 ValueKind::Enum(self.id)
746 }
747
748 pub fn size_of(&self) -> usize {
749 self.variants.iter().map(|(_,v)| v.as_ref().map_or(0, |x| x.size_of())).sum()
750 }
751
752 pub fn pretty_print(&self) -> String {
753 let mut builder = Builder::default();
754 let string_elements: Vec<String> = vec![format!("{}{:?}",self.id,self.variants)];
755 builder.push_record(string_elements);
756 let mut table = builder.build();
757 table.with(Style::modern_rounded());
758 format!("{table}")
759 }
760
761}
762
763impl Hash for MechEnum {
764 fn hash<H: Hasher>(&self, state: &mut H) {
765 self.id.hash(state);
766 self.variants.hash(state);
767 }
768}