1use derive_more::{Display, FromStr};
2use enum_iterator::Sequence;
3use num::Zero as _;
4use serde::{Deserialize, Serialize};
5use surfer_translation_types::VariableValue;
6
7#[derive(
14 Clone, Copy, Debug, Default, Deserialize, Display, FromStr, PartialEq, Eq, Sequence, Serialize,
15)]
16pub enum TraceStyle {
17 #[default]
18 Default,
19 Dinotrace,
20 Zero,
21}
22
23#[derive(Clone, Copy)]
30pub(crate) enum TraceValue {
31 Normal,
32 AllZeros,
33 AllZerosThick,
34 AllOnes,
35}
36
37impl TraceValue {
38 pub(crate) fn from_value(
57 val: &VariableValue,
58 num_bits: Option<u32>,
59 trace_style: TraceStyle,
60 ) -> Self {
61 if trace_style == TraceStyle::Default {
62 return Self::Normal;
63 }
64 match val {
65 VariableValue::BigUint(u) if u.is_zero() => {
66 if trace_style == TraceStyle::Dinotrace {
67 TraceValue::AllZerosThick
68 } else {
69 TraceValue::AllZeros
70 }
71 }
72 VariableValue::BigUint(u)
73 if trace_style == TraceStyle::Dinotrace
74 && num_bits.is_some_and(|bits| u.count_ones() == u64::from(bits)) =>
75 {
76 TraceValue::AllOnes
77 }
78 VariableValue::BigUint(_) => TraceValue::Normal,
79 VariableValue::String(_) => TraceValue::Normal,
80 }
81 }
82}
83
84#[cfg(test)]
85mod tests {
86 use super::*;
87
88 #[test]
89 fn test_default_style_returns_normal() {
90 let val = VariableValue::BigUint(42u32.into());
91 let result = TraceValue::from_value(&val, Some(8), TraceStyle::Default);
92 assert!(matches!(result, TraceValue::Normal));
93 }
94
95 #[test]
96 fn test_dinotrace_all_zeros() {
97 let val = VariableValue::BigUint(0u32.into());
98 let result = TraceValue::from_value(&val, Some(8), TraceStyle::Dinotrace);
99 assert!(matches!(result, TraceValue::AllZerosThick));
100 }
101
102 #[test]
103 fn test_dinotrace_all_ones_8bit() {
104 let val = VariableValue::BigUint(255u32.into()); let result = TraceValue::from_value(&val, Some(8), TraceStyle::Dinotrace);
106 assert!(matches!(result, TraceValue::AllOnes));
107 }
108
109 #[test]
110 fn test_dinotrace_all_ones_32bit() {
111 let val = VariableValue::BigUint(u32::MAX.into());
112 let result = TraceValue::from_value(&val, Some(32), TraceStyle::Dinotrace);
113 assert!(matches!(result, TraceValue::AllOnes));
114 }
115
116 #[test]
117 fn test_dinotrace_partial_value() {
118 let val = VariableValue::BigUint(127u32.into()); let result = TraceValue::from_value(&val, Some(8), TraceStyle::Dinotrace);
120 assert!(matches!(result, TraceValue::Normal));
121 }
122
123 #[test]
124 fn test_dinotrace_no_num_bits() {
125 let val = VariableValue::BigUint(255u32.into());
126 let result = TraceValue::from_value(&val, None, TraceStyle::Dinotrace);
127 assert!(matches!(result, TraceValue::Normal));
129 }
130
131 #[test]
132 fn test_zero_style_all_zeros() {
133 let val = VariableValue::BigUint(0u32.into());
134 let result = TraceValue::from_value(&val, Some(8), TraceStyle::Zero);
135 assert!(matches!(result, TraceValue::AllZeros));
136 }
137
138 #[test]
139 fn test_zero_style_nonzero() {
140 let val = VariableValue::BigUint(42u32.into());
141 let result = TraceValue::from_value(&val, Some(8), TraceStyle::Zero);
142 assert!(matches!(result, TraceValue::Normal));
143 }
144
145 #[test]
146 fn test_zero_style_all_ones() {
147 let val = VariableValue::BigUint(255u32.into());
148 let result = TraceValue::from_value(&val, Some(8), TraceStyle::Zero);
149 assert!(matches!(result, TraceValue::Normal));
151 }
152
153 #[test]
154 fn test_string_value_is_normal() {
155 let val = VariableValue::String("hello".to_string());
156 let result = TraceValue::from_value(&val, Some(8), TraceStyle::Dinotrace);
157 assert!(matches!(result, TraceValue::Normal));
158 }
159}