1use super::{TranslationPreference, ValueKind, VariableInfo};
2use crate::wave_container::{ScopeId, VarId, VariableMeta};
3
4use eyre::Result;
5use itertools::Itertools;
6use num::{One, ToPrimitive, Zero};
7use surfer_translation_types::{
8 BasicTranslator, NumericRange, VariableValue, check_vector_variable, extend_string,
9 kind_for_binary_representation, parse_value_to_numeric,
10};
11
12use super::integer_numeric_range;
13
14#[must_use]
18pub(crate) fn group_n_chars(s: &str, n: usize) -> Vec<&str> {
19 let mut groups = Vec::new();
20 let len = s.len();
21 let rem = len % n;
22 let mut start = 0;
23 if rem > 0 {
24 groups.push(&s[0..rem]);
25 start = rem;
26 }
27 while start < len {
28 let end = (start + n).min(len);
29 groups.push(&s[start..end]);
30 start += n;
31 }
32 groups
33}
34
35fn map_to_radix(s: &str, radix: usize, num_bits: u32) -> (String, ValueKind) {
37 let mut had_invalid_digit = false;
38 let formatted = group_n_chars(
39 &format!("{extra_bits}{s}", extra_bits = extend_string(s, num_bits)),
40 radix,
41 )
42 .into_iter()
43 .map(|g| match g {
44 g if g.contains('x') => "x".to_string(),
45 g if g.contains('z') => "z".to_string(),
46 g if g.contains('-') => "-".to_string(),
47 g if g.contains('u') => "u".to_string(),
48 g if g.contains('w') => "w".to_string(),
49 g if g.contains('h') => "h".to_string(),
50 g if g.contains('l') => "l".to_string(),
51 g => {
52 if let Ok(val) = u8::from_str_radix(g, 2) {
53 format!("{val:x}")
54 } else {
55 had_invalid_digit = true;
56 "?".to_string()
57 }
58 }
59 })
60 .join("");
61
62 let kind = if had_invalid_digit {
63 ValueKind::Error
64 } else {
65 kind_for_binary_representation(&formatted)
66 };
67 (formatted, kind)
68}
69
70fn check_wordlength(
71 num_bits: Option<u32>,
72 required: impl FnOnce(u32) -> bool,
73) -> Result<TranslationPreference> {
74 if let Some(num_bits) = num_bits {
75 if required(num_bits) {
76 Ok(TranslationPreference::Yes)
77 } else {
78 Ok(TranslationPreference::No)
79 }
80 } else {
81 Ok(TranslationPreference::No)
82 }
83}
84
85pub struct HexTranslator {}
86
87impl BasicTranslator<VarId, ScopeId> for HexTranslator {
88 fn name(&self) -> String {
89 String::from("Hexadecimal")
90 }
91
92 fn basic_translate(&self, num_bits: u32, value: &VariableValue) -> (String, ValueKind) {
93 match value {
94 VariableValue::BigUint(v) => (
95 format!("{v:0width$x}", width = num_bits.div_ceil(4) as usize),
96 ValueKind::Normal,
97 ),
98 VariableValue::String(s) => map_to_radix(s, 4, num_bits),
99 }
100 }
101
102 fn basic_numeric_range(&self, num_bits: u32) -> Option<NumericRange> {
103 integer_numeric_range(num_bits, false)
104 }
105}
106
107pub struct BitTranslator {}
108
109impl BasicTranslator<VarId, ScopeId> for BitTranslator {
110 fn name(&self) -> String {
111 String::from("Bit")
112 }
113
114 fn basic_translate(&self, _num_bits: u32, value: &VariableValue) -> (String, ValueKind) {
115 match value {
116 VariableValue::BigUint(v) => (
117 if (*v).is_zero() {
118 "0".to_string()
119 } else if (*v).is_one() {
120 "1".to_string()
121 } else {
122 "-".to_string()
123 },
124 ValueKind::Normal,
125 ),
126 VariableValue::String(s) => (s.clone(), kind_for_binary_representation(s)),
127 }
128 }
129
130 fn translates(&self, variable: &VariableMeta) -> Result<TranslationPreference> {
131 if let Some(num_bits) = variable.num_bits {
132 if num_bits == 1u32 {
133 Ok(TranslationPreference::Prefer)
134 } else {
135 Ok(TranslationPreference::No)
136 }
137 } else {
138 Ok(TranslationPreference::No)
139 }
140 }
141
142 fn variable_info(&self, _variable: &VariableMeta) -> Result<VariableInfo> {
143 Ok(VariableInfo::Bool)
144 }
145}
146
147pub struct OctalTranslator {}
148
149impl BasicTranslator<VarId, ScopeId> for OctalTranslator {
150 fn name(&self) -> String {
151 String::from("Octal")
152 }
153
154 fn basic_translate(&self, num_bits: u32, value: &VariableValue) -> (String, ValueKind) {
155 match value {
156 VariableValue::BigUint(v) => (
157 format!("{v:0width$o}", width = num_bits.div_ceil(3) as usize),
158 ValueKind::Normal,
159 ),
160 VariableValue::String(s) => map_to_radix(s, 3, num_bits),
161 }
162 }
163
164 fn basic_numeric_range(&self, num_bits: u32) -> Option<NumericRange> {
165 integer_numeric_range(num_bits, false)
166 }
167}
168
169pub struct GroupingBinaryTranslator {}
170
171impl BasicTranslator<VarId, ScopeId> for GroupingBinaryTranslator {
172 fn name(&self) -> String {
173 String::from("Binary (with groups)")
174 }
175
176 fn basic_translate(&self, num_bits: u32, value: &VariableValue) -> (String, ValueKind) {
177 let (val, color) = match value {
178 VariableValue::BigUint(v) => (
179 format!("{v:0width$b}", width = num_bits as usize),
180 ValueKind::Normal,
181 ),
182 VariableValue::String(s) => (
183 format!("{extra_bits}{s}", extra_bits = extend_string(s, num_bits)),
184 kind_for_binary_representation(s),
185 ),
186 };
187
188 (group_n_chars(&val, 4).join(" "), color)
189 }
190
191 fn basic_numeric_range(&self, num_bits: u32) -> Option<NumericRange> {
192 integer_numeric_range(num_bits, false)
193 }
194}
195
196pub struct BinaryTranslator {}
197
198impl BasicTranslator<VarId, ScopeId> for BinaryTranslator {
199 fn name(&self) -> String {
200 String::from("Binary")
201 }
202
203 fn basic_translate(&self, num_bits: u32, value: &VariableValue) -> (String, ValueKind) {
204 match value {
205 VariableValue::BigUint(v) => (
206 format!("{v:0width$b}", width = num_bits as usize),
207 ValueKind::Normal,
208 ),
209 VariableValue::String(s) => (
210 format!("{extra_bits}{s}", extra_bits = extend_string(s, num_bits)),
211 kind_for_binary_representation(s),
212 ),
213 }
214 }
215
216 fn basic_numeric_range(&self, num_bits: u32) -> Option<NumericRange> {
217 integer_numeric_range(num_bits, false)
218 }
219}
220
221pub struct ASCIITranslator {}
222
223impl BasicTranslator<VarId, ScopeId> for ASCIITranslator {
224 fn name(&self) -> String {
225 String::from("ASCII")
226 }
227
228 fn basic_translate(&self, _num_bits: u32, value: &VariableValue) -> (String, ValueKind) {
229 match value {
230 VariableValue::BigUint(v) => (
231 v.to_bytes_be()
232 .into_iter()
233 .map(|val| (val as char).to_string())
234 .join(""),
235 ValueKind::Normal,
236 ),
237 VariableValue::String(s) => match check_vector_variable(s) {
238 Some(v) => v,
239 None => (
240 group_n_chars(s, 8)
241 .into_iter()
242 .map(|substr| {
243 format!(
244 "{cval}",
245 cval = u8::from_str_radix(substr, 2).unwrap_or_else(|_| panic!(
246 "Found non-binary digit {substr} in value"
247 )) as char
248 )
249 })
250 .join(""),
251 ValueKind::Normal,
252 ),
253 },
254 }
255 }
256}
257
258fn decode_lebxxx(value: &num::BigUint) -> Result<num::BigUint, &'static str> {
259 let bytes = value.to_bytes_be();
260 match bytes.first() {
261 Some(b) if b & 0x80 != 0 => return Err("invalid MSB"),
262 _ => (),
263 }
264
265 let first: num::BigUint = bytes.first().copied().unwrap_or(0).into();
266 bytes.iter().skip(1).try_fold(first, |result, b| {
267 if (b & 0x80 == 0) == (result.is_zero()) {
268 Ok((result << 7) + (*b & 0x7f))
269 } else {
270 Err("invalid flag")
271 }
272 })
273}
274
275pub struct LebTranslator {}
276
277impl BasicTranslator<VarId, ScopeId> for LebTranslator {
278 fn name(&self) -> String {
279 "LEBxxx".to_string()
280 }
281
282 fn basic_translate(&self, num_bits: u32, value: &VariableValue) -> (String, ValueKind) {
283 let decoded = match value {
284 VariableValue::BigUint(v) => decode_lebxxx(v),
285 VariableValue::String(s) => match check_vector_variable(s) {
286 Some(v) => return v,
287 None => match num::BigUint::parse_bytes(s.as_bytes(), 2) {
288 Some(bi) => decode_lebxxx(&bi),
289 None => return ("INVALID".to_owned(), ValueKind::Warn),
290 },
291 },
292 };
293
294 match decoded {
295 Ok(decoded) => (decoded.to_str_radix(10), ValueKind::Normal),
296 Err(s) => (
297 s.to_owned()
298 + ": "
299 + &GroupingBinaryTranslator {}
300 .basic_translate(num_bits, value)
301 .0,
302 ValueKind::Warn,
303 ),
304 }
305 }
306
307 fn translates(&self, variable: &VariableMeta) -> Result<TranslationPreference> {
308 check_wordlength(variable.num_bits, |n| (n.is_multiple_of(8)) && n > 0)
309 }
310}
311
312pub struct NumberOfOnesTranslator {}
313
314impl BasicTranslator<VarId, ScopeId> for NumberOfOnesTranslator {
315 fn name(&self) -> String {
316 String::from("Number of ones")
317 }
318
319 fn basic_translate(&self, _num_bits: u32, value: &VariableValue) -> (String, ValueKind) {
320 match value {
321 VariableValue::BigUint(v) => (v.count_ones().to_string(), ValueKind::Normal),
322 VariableValue::String(s) => (
323 s.bytes().filter(|b| *b == b'1').count().to_string(),
324 kind_for_binary_representation(s),
325 ),
326 }
327 }
328
329 fn basic_translate_numeric(&self, _num_bits: u32, value: &VariableValue) -> Option<f64> {
330 Some(parse_value_to_numeric(value, |v| v.count_ones() as f64))
331 }
332}
333
334pub struct TrailingOnesTranslator {}
335
336impl BasicTranslator<VarId, ScopeId> for TrailingOnesTranslator {
337 fn name(&self) -> String {
338 String::from("Trailing ones")
339 }
340
341 fn basic_translate(&self, _num_bits: u32, value: &VariableValue) -> (String, ValueKind) {
342 match value {
343 VariableValue::BigUint(v) => (v.trailing_ones().to_string(), ValueKind::Normal),
344 VariableValue::String(s) => (
345 s.bytes()
346 .rev()
347 .take_while(|b| *b == b'1')
348 .count()
349 .to_string(),
350 kind_for_binary_representation(s),
351 ),
352 }
353 }
354
355 fn basic_translate_numeric(&self, _num_bits: u32, value: &VariableValue) -> Option<f64> {
356 Some(parse_value_to_numeric(value, |v| v.trailing_ones() as f64))
357 }
358}
359
360pub struct TrailingZerosTranslator {}
361
362impl BasicTranslator<VarId, ScopeId> for TrailingZerosTranslator {
363 fn name(&self) -> String {
364 String::from("Trailing zeros")
365 }
366
367 fn basic_translate(&self, num_bits: u32, value: &VariableValue) -> (String, ValueKind) {
368 match value {
369 VariableValue::BigUint(v) => (
370 v.trailing_zeros()
371 .unwrap_or(u64::from(num_bits))
372 .to_string(),
373 ValueKind::Normal,
374 ),
375 VariableValue::String(s) => (
376 (extend_string(s, num_bits) + s)
377 .bytes()
378 .rev()
379 .take_while(|b| *b == b'0')
380 .count()
381 .to_string(),
382 kind_for_binary_representation(s),
383 ),
384 }
385 }
386
387 fn basic_translate_numeric(&self, num_bits: u32, value: &VariableValue) -> Option<f64> {
388 Some(parse_value_to_numeric(value, |v| {
389 v.trailing_zeros().unwrap_or(u64::from(num_bits)) as f64
390 }))
391 }
392}
393
394pub struct LeadingOnesTranslator {}
395
396impl BasicTranslator<VarId, ScopeId> for LeadingOnesTranslator {
397 fn name(&self) -> String {
398 String::from("Leading ones")
399 }
400
401 fn basic_translate(&self, num_bits: u32, value: &VariableValue) -> (String, ValueKind) {
402 match value {
403 VariableValue::BigUint(v) => {
404 let s = format!("{v:0width$b}", width = num_bits as usize);
405 self.basic_translate(num_bits, &VariableValue::String(s))
406 }
407 VariableValue::String(s) => (
408 if s.len() == (num_bits as usize) {
409 s.bytes().take_while(|b| *b == b'1').count().to_string()
410 } else {
411 "0".to_string()
412 },
413 kind_for_binary_representation(s),
414 ),
415 }
416 }
417
418 fn basic_translate_numeric(&self, num_bits: u32, value: &VariableValue) -> Option<f64> {
419 Some(parse_value_to_numeric(value, |v| {
420 leading_ones(v, u64::from(num_bits)) as f64
421 }))
422 }
423}
424
425pub struct LeadingZerosTranslator {}
426
427impl BasicTranslator<VarId, ScopeId> for LeadingZerosTranslator {
428 fn name(&self) -> String {
429 String::from("Leading zeros")
430 }
431
432 fn basic_translate(&self, num_bits: u32, value: &VariableValue) -> (String, ValueKind) {
433 match value {
434 VariableValue::BigUint(v) => {
435 let s = format!("{v:0width$b}", width = num_bits as usize);
436 self.basic_translate(num_bits, &VariableValue::String(s))
437 }
438 VariableValue::String(s) => (
439 (extend_string(s, num_bits) + s)
440 .bytes()
441 .take_while(|b| *b == b'0')
442 .count()
443 .to_string(),
444 kind_for_binary_representation(s),
445 ),
446 }
447 }
448
449 fn basic_translate_numeric(&self, num_bits: u32, value: &VariableValue) -> Option<f64> {
450 Some(parse_value_to_numeric(value, |v| {
451 u64::from(num_bits).saturating_sub(v.bits()) as f64
452 }))
453 }
454}
455
456fn leading_ones(v: &num::BigUint, num_bits: u64) -> u64 {
459 if v.bits() < num_bits {
460 0
461 } else {
462 let mask = (num::BigUint::one() << num_bits) - 1u32;
463 num_bits.saturating_sub((mask ^ v).bits())
464 }
465}
466
467pub struct IdenticalMSBsTranslator {}
468
469impl BasicTranslator<VarId, ScopeId> for IdenticalMSBsTranslator {
470 fn name(&self) -> String {
471 String::from("Identical MSBs")
472 }
473
474 fn basic_translate(&self, num_bits: u32, value: &VariableValue) -> (String, ValueKind) {
475 match value {
476 VariableValue::BigUint(v) => {
477 let s = format!("{v:0width$b}", width = num_bits as usize);
478 self.basic_translate(num_bits, &VariableValue::String(s))
479 }
480 VariableValue::String(s) => {
481 let extended_string = extend_string(s, num_bits) + s;
482 let zeros = extended_string.bytes().take_while(|b| *b == b'0').count();
483 let ones = extended_string.bytes().take_while(|b| *b == b'1').count();
484 let count = ones.max(zeros);
485 (count.to_string(), kind_for_binary_representation(s))
486 }
487 }
488 }
489
490 fn basic_translate_numeric(&self, num_bits: u32, value: &VariableValue) -> Option<f64> {
491 Some(parse_value_to_numeric(value, |v| {
492 let num_bits = u64::from(num_bits);
493 let lz = num_bits.saturating_sub(v.bits());
494 let lo = leading_ones(v, num_bits);
495 lz.max(lo) as f64
496 }))
497 }
498}
499
500pub struct GrayCodeTranslator {}
501
502fn decode_gray(mut value: num::BigUint) -> num::BigUint {
503 let mut mask = value.clone();
504 while !mask.is_zero() {
505 mask >>= 1;
506 value ^= &mask;
507 }
508 value
509}
510
511impl BasicTranslator<VarId, ScopeId> for GrayCodeTranslator {
512 fn name(&self) -> String {
513 String::from("Gray code (RBC)")
514 }
515
516 fn basic_translate(&self, _num_bits: u32, value: &VariableValue) -> (String, ValueKind) {
517 let decoded = match value {
518 VariableValue::BigUint(v) => decode_gray(v.clone()),
519 VariableValue::String(s) => match check_vector_variable(s) {
520 Some(v) => return v,
521 None => match num::BigUint::parse_bytes(s.as_bytes(), 2) {
522 Some(bi) => decode_gray(bi),
523 None => return ("INVALID".to_string(), ValueKind::Warn),
524 },
525 },
526 };
527
528 (decoded.to_str_radix(10), ValueKind::Normal)
529 }
530
531 fn basic_translate_numeric(&self, _num_bits: u32, value: &VariableValue) -> Option<f64> {
532 Some(parse_value_to_numeric(value, |v| {
533 decode_gray(v.clone()).to_f64().unwrap_or(f64::NAN)
534 }))
535 }
536}
537
538#[cfg(test)]
539mod test {
540
541 use num::{BigUint, FromPrimitive};
542
543 use super::*;
544
545 #[test]
546 fn group_n_chars_splits_with_remainder() {
547 assert_eq!(group_n_chars("101010", 4), vec!["10", "1010"]);
548 }
549
550 #[test]
551 fn group_n_chars_splits_evenly() {
552 assert_eq!(group_n_chars("10101010", 4), vec!["1010", "1010"]);
553 }
554
555 #[test]
556 fn group_n_chars_handles_empty_input() {
557 assert_eq!(group_n_chars("", 4), Vec::<&str>::new());
558 }
559
560 #[test]
561 fn map_to_radix_formats_binary_groups() {
562 let (formatted, kind) = map_to_radix("10000", 4, 5);
563 assert_eq!(formatted, "10");
564 assert_eq!(kind, ValueKind::Normal);
565 }
566
567 #[test]
568 fn map_to_radix_prefers_special_digits_per_group() {
569 let (formatted, kind) = map_to_radix("zx01", 4, 4);
570 assert_eq!(formatted, "x");
571 assert_eq!(kind, kind_for_binary_representation("x"));
572 }
573
574 #[test]
575 fn map_to_radix_marks_invalid_binary_digit_as_error() {
576 let (formatted, kind) = map_to_radix("1002", 4, 4);
577 assert_eq!(formatted, "?");
578 assert_eq!(kind, ValueKind::Error);
579 }
580
581 #[test]
582 fn check_wordlength_returns_yes_when_predicate_matches() {
583 let preference = check_wordlength(Some(16), |n| n.is_multiple_of(8)).unwrap();
584 assert_eq!(preference, TranslationPreference::Yes);
585 }
586
587 #[test]
588 fn check_wordlength_returns_no_for_missing_or_nonmatching_wordlength() {
589 let missing = check_wordlength(None, |n| n.is_multiple_of(8)).unwrap();
590 assert_eq!(missing, TranslationPreference::No);
591
592 let nonmatching = check_wordlength(Some(7), |n| n.is_multiple_of(8)).unwrap();
593 assert_eq!(nonmatching, TranslationPreference::No);
594 }
595
596 #[test]
597 fn decode_lebxxx_decodes_valid_value() {
598 let decoded = decode_lebxxx(&BigUint::from(0b01011010_11101111u16)).unwrap();
599 assert_eq!(decoded, BigUint::from(11_631u32));
600 }
601
602 #[test]
603 fn decode_lebxxx_rejects_invalid_msb() {
604 let err = decode_lebxxx(&BigUint::from(0b10000000u8)).unwrap_err();
605 assert_eq!(err, "invalid MSB");
606 }
607
608 #[test]
609 fn hexadecimal_translation_groups_digits_correctly_string() {
610 assert_eq!(
611 HexTranslator {}
612 .basic_translate(5, &VariableValue::String("10000".to_string()))
613 .0,
614 "10"
615 );
616
617 assert_eq!(
618 HexTranslator {}
619 .basic_translate(5, &VariableValue::String("1000".to_string()))
620 .0,
621 "08"
622 );
623
624 assert_eq!(
625 HexTranslator {}
626 .basic_translate(5, &VariableValue::String("100000".to_string()))
627 .0,
628 "20"
629 );
630 assert_eq!(
631 HexTranslator {}
632 .basic_translate(10, &VariableValue::String("1z00x0".to_string()))
633 .0,
634 "0zx"
635 );
636 assert_eq!(
637 HexTranslator {}
638 .basic_translate(10, &VariableValue::String("z0110".to_string()))
639 .0,
640 "zz6"
641 );
642 assert_eq!(
643 HexTranslator {}
644 .basic_translate(24, &VariableValue::String("xz0110".to_string()))
645 .0,
646 "xxxxx6"
647 );
648 }
649
650 #[test]
651 fn hexadecimal_translation_groups_digits_correctly_bigint() {
652 assert_eq!(
653 HexTranslator {}
654 .basic_translate(5, &VariableValue::BigUint(BigUint::from(0b10000u32)))
655 .0,
656 "10"
657 );
658 assert_eq!(
659 HexTranslator {}
660 .basic_translate(5, &VariableValue::BigUint(BigUint::from(0b1000u32)))
661 .0,
662 "08"
663 );
664 assert_eq!(
665 HexTranslator {}
666 .basic_translate(5, &VariableValue::BigUint(BigUint::from(0u32)))
667 .0,
668 "00"
669 );
670 }
671
672 #[test]
673 fn octal_translation_groups_digits_correctly_string() {
674 assert_eq!(
675 OctalTranslator {}
676 .basic_translate(5, &VariableValue::String("10000".to_string()))
677 .0,
678 "20"
679 );
680 assert_eq!(
681 OctalTranslator {}
682 .basic_translate(5, &VariableValue::String("100".to_string()))
683 .0,
684 "04"
685 );
686 assert_eq!(
687 OctalTranslator {}
688 .basic_translate(9, &VariableValue::String("x100".to_string()))
689 .0,
690 "xx4"
691 );
692 }
693
694 #[test]
695 fn octal_translation_groups_digits_correctly_bigint() {
696 assert_eq!(
697 OctalTranslator {}
698 .basic_translate(5, &VariableValue::BigUint(BigUint::from(0b10000u32)))
699 .0,
700 "20"
701 );
702 assert_eq!(
703 OctalTranslator {}
704 .basic_translate(5, &VariableValue::BigUint(BigUint::from(0b00100u32)))
705 .0,
706 "04"
707 );
708 }
709
710 #[test]
711 fn grouping_binary_translation_groups_digits_correctly_string() {
712 assert_eq!(
713 GroupingBinaryTranslator {}
714 .basic_translate(5, &VariableValue::String("1000w".to_string()))
715 .0,
716 "1 000w"
717 );
718 assert_eq!(
719 GroupingBinaryTranslator {}
720 .basic_translate(8, &VariableValue::String("100l00".to_string()))
721 .0,
722 "0010 0l00"
723 );
724 assert_eq!(
725 GroupingBinaryTranslator {}
726 .basic_translate(7, &VariableValue::String("10x00".to_string()))
727 .0,
728 "001 0x00"
729 );
730 assert_eq!(
731 GroupingBinaryTranslator {}
732 .basic_translate(7, &VariableValue::String("z10x00".to_string()))
733 .0,
734 "zz1 0x00"
735 );
736 }
737
738 #[test]
739 fn grouping_binary_translation_groups_digits_correctly_bigint() {
740 assert_eq!(
741 GroupingBinaryTranslator {}
742 .basic_translate(7, &VariableValue::BigUint(BigUint::from(0b100000u32)))
743 .0,
744 "010 0000"
745 );
746 }
747
748 #[test]
749 fn binary_translation_groups_digits_correctly_string() {
750 assert_eq!(
751 BinaryTranslator {}
752 .basic_translate(5, &VariableValue::String("10000".to_string()))
753 .0,
754 "10000"
755 );
756 assert_eq!(
757 BinaryTranslator {}
758 .basic_translate(8, &VariableValue::String("100h00".to_string()))
759 .0,
760 "00100h00"
761 );
762 assert_eq!(
763 BinaryTranslator {}
764 .basic_translate(7, &VariableValue::String("10x0-".to_string()))
765 .0,
766 "0010x0-"
767 );
768 assert_eq!(
769 BinaryTranslator {}
770 .basic_translate(7, &VariableValue::String("z10x00".to_string()))
771 .0,
772 "zz10x00"
773 );
774 }
775
776 #[test]
777 fn binary_translation_groups_digits_correctly_bigint() {
778 assert_eq!(
779 BinaryTranslator {}
780 .basic_translate(7, &VariableValue::BigUint(BigUint::from(0b100000u32)))
781 .0,
782 "0100000"
783 );
784 }
785
786 #[test]
787 fn ascii_translation_from_biguint() {
788 assert_eq!(
789 ASCIITranslator {}
790 .basic_translate(
791 15,
792 &VariableValue::BigUint(BigUint::from(0b100111101001011u32))
793 )
794 .0,
795 "OK"
796 );
797 assert_eq!(
798 ASCIITranslator {}
799 .basic_translate(72, &VariableValue::BigUint(BigUint::from(0b010011000110111101101110011001110010000001110100011001010111001101110100u128)))
800 .0,
801 "Long test"
802 );
803 }
804
805 #[test]
806 fn ascii_translation_from_string() {
807 assert_eq!(
808 ASCIITranslator {}
809 .basic_translate(15, &VariableValue::String("100111101001011".to_string()))
810 .0,
811 "OK"
812 );
813 assert_eq!(
814 ASCIITranslator {}
815 .basic_translate(
816 72,
817 &VariableValue::String(
818 "010011000110111101101110011001110010000001110100011001010111001101110100"
819 .to_string()
820 )
821 )
822 .0,
823 "Long test"
824 );
825 assert_eq!(
826 ASCIITranslator {}
827 .basic_translate(16, &VariableValue::String("010x111101001011".to_string()))
828 .0,
829 "UNDEF"
830 );
831 assert_eq!(
833 ASCIITranslator {}
834 .basic_translate(15, &VariableValue::String("11000001001011".to_string()))
835 .0,
836 "0K"
837 );
838 }
839
840 #[test]
841 fn bit_translation_from_biguint() {
842 assert_eq!(
843 BitTranslator {}
844 .basic_translate(1, &VariableValue::BigUint(BigUint::from(0b1u8)))
845 .0,
846 "1"
847 );
848 assert_eq!(
849 BitTranslator {}
850 .basic_translate(1, &VariableValue::BigUint(BigUint::from(0b0u8)))
851 .0,
852 "0"
853 );
854 }
855
856 #[test]
857 fn bit_translation_from_string() {
858 assert_eq!(
859 BitTranslator {}
860 .basic_translate(1, &VariableValue::String("1".to_string()))
861 .0,
862 "1"
863 );
864 assert_eq!(
865 BitTranslator {}
866 .basic_translate(1, &VariableValue::String("0".to_string()))
867 .0,
868 "0"
869 );
870 assert_eq!(
871 BitTranslator {}
872 .basic_translate(1, &VariableValue::String("x".to_string()))
873 .0,
874 "x"
875 );
876 }
877
878 #[test]
879 fn bit_translator_with_invalid_data() {
880 assert_eq!(
881 BitTranslator {}
882 .basic_translate(2, &VariableValue::BigUint(BigUint::from(3u8)))
883 .0,
884 "-"
885 );
886 }
887
888 #[test]
889 fn leb_translation_from_biguint() {
890 assert_eq!(
891 LebTranslator {}
892 .basic_translate(16, &VariableValue::BigUint(0b01011010_11101111u16.into()))
893 .0,
894 "11631"
895 );
896 assert_eq!(
897 LebTranslator {}
898 .basic_translate(16, &VariableValue::BigUint(0b00000000_00000001u16.into()))
899 .0,
900 "1"
901 );
902 assert_eq!(
903 LebTranslator{}.basic_translate(64, &VariableValue::BigUint(0b01001010_11110111_11101000_10100000_10111010_11110110_11100001_10011001u64.into())).0, "42185246214303897"
904 );
905 }
906 #[test]
907 fn leb_translation_from_string() {
908 assert_eq!(
909 LebTranslator {}
910 .basic_translate(16, &VariableValue::String("0111110011100010".to_owned()))
911 .0,
912 "15970"
913 );
914 }
915 #[test]
916 fn leb_translation_invalid_msb() {
917 assert_eq!(
918 LebTranslator {}
919 .basic_translate(16, &VariableValue::BigUint(0b1000000010000000u16.into()))
920 .0,
921 "invalid MSB: 1000 0000 1000 0000"
922 );
923 }
924 #[test]
925 fn leb_translation_invalid_continuation() {
926 assert_eq!(
927 LebTranslator {}
928 .basic_translate(16, &VariableValue::BigUint(0b0111111101111111u16.into()))
929 .0,
930 "invalid flag: 0111 1111 0111 1111"
931 );
932 }
933
934 #[test]
935 fn leb_tranlator_input_not_multiple_of_8() {
936 assert_eq!(
938 LebTranslator {}
939 .basic_translate(16, &VariableValue::BigUint(0b00001111111u16.into()))
940 .0,
941 "127"
942 );
943 }
944
945 #[test]
946 fn number_of_ones_translation_string() {
947 assert_eq!(
948 NumberOfOnesTranslator {}
949 .basic_translate(5, &VariableValue::String("10000".to_string()))
950 .0,
951 "1"
952 );
953 assert_eq!(
954 NumberOfOnesTranslator {}
955 .basic_translate(5, &VariableValue::String("101".to_string()))
956 .0,
957 "2"
958 );
959 assert_eq!(
960 NumberOfOnesTranslator {}
961 .basic_translate(9, &VariableValue::String("1x100".to_string()))
962 .0,
963 "2"
964 );
965 }
966
967 #[test]
968 fn number_of_ones_translation_bigint() {
969 assert_eq!(
970 NumberOfOnesTranslator {}
971 .basic_translate(17, &VariableValue::BigUint(BigUint::from(0b101110000u32)))
972 .0,
973 "4"
974 );
975 assert_eq!(
976 NumberOfOnesTranslator {}
977 .basic_translate(40, &VariableValue::BigUint(BigUint::from(0b00100u32)))
978 .0,
979 "1"
980 );
981 }
982
983 #[test]
984 fn trailing_ones_translation_string() {
985 assert_eq!(
986 TrailingOnesTranslator {}
987 .basic_translate(5, &VariableValue::String("10111".to_string()))
988 .0,
989 "3"
990 );
991 assert_eq!(
992 TrailingOnesTranslator {}
993 .basic_translate(5, &VariableValue::String("101".to_string()))
994 .0,
995 "1"
996 );
997 assert_eq!(
998 TrailingOnesTranslator {}
999 .basic_translate(9, &VariableValue::String("x100".to_string()))
1000 .0,
1001 "0"
1002 );
1003 }
1004
1005 #[test]
1006 fn trailing_ones_translation_bigint() {
1007 assert_eq!(
1008 TrailingOnesTranslator {}
1009 .basic_translate(17, &VariableValue::BigUint(BigUint::from(0b101111111u32)))
1010 .0,
1011 "7"
1012 );
1013 assert_eq!(
1014 TrailingOnesTranslator {}
1015 .basic_translate(40, &VariableValue::BigUint(BigUint::from(0b00100u32)))
1016 .0,
1017 "0"
1018 );
1019 assert_eq!(
1020 TrailingOnesTranslator {}
1021 .basic_translate(5, &VariableValue::BigUint(BigUint::from(0b11111u32)))
1022 .0,
1023 "5"
1024 );
1025 }
1026
1027 #[test]
1028 fn trailing_zeros_translation_string() {
1029 assert_eq!(
1030 TrailingZerosTranslator {}
1031 .basic_translate(5, &VariableValue::String("10000".to_string()))
1032 .0,
1033 "4"
1034 );
1035 assert_eq!(
1036 TrailingZerosTranslator {}
1037 .basic_translate(5, &VariableValue::String("101".to_string()))
1038 .0,
1039 "0"
1040 );
1041 assert_eq!(
1042 TrailingZerosTranslator {}
1043 .basic_translate(9, &VariableValue::String("x100".to_string()))
1044 .0,
1045 "2"
1046 );
1047 }
1048
1049 #[test]
1050 fn trailing_zeros_translation_bigint() {
1051 assert_eq!(
1052 TrailingZerosTranslator {}
1053 .basic_translate(17, &VariableValue::BigUint(BigUint::from(0b101111111u32)))
1054 .0,
1055 "0"
1056 );
1057 assert_eq!(
1058 TrailingZerosTranslator {}
1059 .basic_translate(40, &VariableValue::BigUint(BigUint::from(0b00100u32)))
1060 .0,
1061 "2"
1062 );
1063 assert_eq!(
1064 TrailingZerosTranslator {}
1065 .basic_translate(16, &VariableValue::BigUint(BigUint::from(0b0u32)))
1066 .0,
1067 "16"
1068 );
1069 }
1070
1071 #[test]
1072 fn leading_ones_translation_string() {
1073 assert_eq!(
1074 LeadingOnesTranslator {}
1075 .basic_translate(5, &VariableValue::String("11101".to_string()))
1076 .0,
1077 "3"
1078 );
1079 assert_eq!(
1080 LeadingOnesTranslator {}
1081 .basic_translate(5, &VariableValue::String("101".to_string()))
1082 .0,
1083 "0"
1084 );
1085 assert_eq!(
1086 LeadingOnesTranslator {}
1087 .basic_translate(9, &VariableValue::String("x100".to_string()))
1088 .0,
1089 "0"
1090 );
1091 }
1092
1093 #[test]
1094 fn leading_ones_translation_bigint() {
1095 assert_eq!(
1096 LeadingOnesTranslator {}
1097 .basic_translate(11, &VariableValue::BigUint(BigUint::from(0b11111111100u32)))
1098 .0,
1099 "9"
1100 );
1101 assert_eq!(
1102 LeadingOnesTranslator {}
1103 .basic_translate(40, &VariableValue::BigUint(BigUint::from(0b00100u32)))
1104 .0,
1105 "0"
1106 );
1107 assert_eq!(
1108 LeadingOnesTranslator {}
1109 .basic_translate(5, &VariableValue::BigUint(BigUint::from(0b11111u32)))
1110 .0,
1111 "5"
1112 );
1113 }
1114
1115 #[test]
1116 fn leading_zeros_translation_string() {
1117 assert_eq!(
1118 LeadingZerosTranslator {}
1119 .basic_translate(5, &VariableValue::String("10000".to_string()))
1120 .0,
1121 "0"
1122 );
1123 assert_eq!(
1124 LeadingZerosTranslator {}
1125 .basic_translate(5, &VariableValue::String("101".to_string()))
1126 .0,
1127 "2"
1128 );
1129 assert_eq!(
1130 LeadingZerosTranslator {}
1131 .basic_translate(9, &VariableValue::String("x100".to_string()))
1132 .0,
1133 "0"
1134 );
1135 }
1136
1137 #[test]
1138 fn leading_zeros_translation_bigint() {
1139 assert_eq!(
1140 LeadingZerosTranslator {}
1141 .basic_translate(17, &VariableValue::BigUint(BigUint::from(0b101111111u32)))
1142 .0,
1143 "8"
1144 );
1145 assert_eq!(
1146 LeadingZerosTranslator {}
1147 .basic_translate(40, &VariableValue::BigUint(BigUint::from(0b00100u32)))
1148 .0,
1149 "37"
1150 );
1151 assert_eq!(
1152 LeadingZerosTranslator {}
1153 .basic_translate(16, &VariableValue::BigUint(BigUint::from(0b0u32)))
1154 .0,
1155 "16"
1156 );
1157 }
1158
1159 #[test]
1160 fn signbits_translation_string() {
1161 assert_eq!(
1162 IdenticalMSBsTranslator {}
1163 .basic_translate(5, &VariableValue::String("10000".to_string()))
1164 .0,
1165 "1"
1166 );
1167 assert_eq!(
1168 IdenticalMSBsTranslator {}
1169 .basic_translate(7, &VariableValue::String("0".to_string()))
1170 .0,
1171 "7"
1172 );
1173 assert_eq!(
1174 IdenticalMSBsTranslator {}
1175 .basic_translate(5, &VariableValue::String("101".to_string()))
1176 .0,
1177 "2"
1178 );
1179 assert_eq!(
1180 IdenticalMSBsTranslator {}
1181 .basic_translate(9, &VariableValue::String("x100".to_string()))
1182 .0,
1183 "0"
1184 );
1185 assert_eq!(
1186 IdenticalMSBsTranslator {}
1187 .basic_translate(5, &VariableValue::String("11101".to_string()))
1188 .0,
1189 "3"
1190 );
1191 }
1192
1193 #[test]
1194 fn signbits_translation_bigint() {
1195 assert_eq!(
1196 IdenticalMSBsTranslator {}
1197 .basic_translate(17, &VariableValue::BigUint(BigUint::from(0b101111111u32)))
1198 .0,
1199 "8"
1200 );
1201 assert_eq!(
1202 IdenticalMSBsTranslator {}
1203 .basic_translate(40, &VariableValue::BigUint(BigUint::from(0b00100u32)))
1204 .0,
1205 "37"
1206 );
1207 assert_eq!(
1208 IdenticalMSBsTranslator {}
1209 .basic_translate(16, &VariableValue::BigUint(BigUint::from(0b0u32)))
1210 .0,
1211 "16"
1212 );
1213 assert_eq!(
1214 IdenticalMSBsTranslator {}
1215 .basic_translate(11, &VariableValue::BigUint(BigUint::from(0b11111111100u32)))
1216 .0,
1217 "9"
1218 );
1219 assert_eq!(
1220 IdenticalMSBsTranslator {}
1221 .basic_translate(5, &VariableValue::BigUint(BigUint::from(0b11111u32)))
1222 .0,
1223 "5"
1224 );
1225 }
1226
1227 #[test]
1228 fn gray_decoder() {
1229 assert_eq!(
1230 decode_gray(BigUint::from_u32(0b000).unwrap()),
1231 BigUint::from_u32(0).unwrap()
1232 );
1233
1234 assert_eq!(
1235 decode_gray(BigUint::from_u32(0b001).unwrap()),
1236 BigUint::from_u32(1).unwrap()
1237 );
1238
1239 assert_eq!(
1240 decode_gray(BigUint::from_u32(0b011).unwrap()),
1241 BigUint::from_u32(2).unwrap()
1242 );
1243 assert_eq!(
1244 decode_gray(BigUint::from_u32(0b010).unwrap()),
1245 BigUint::from_u32(3).unwrap()
1246 );
1247 assert_eq!(
1248 decode_gray(BigUint::from_u32(0b110).unwrap()),
1249 BigUint::from_u32(4).unwrap()
1250 );
1251 assert_eq!(
1252 decode_gray(BigUint::from_u32(0b111).unwrap()),
1253 BigUint::from_u32(5).unwrap()
1254 );
1255 assert_eq!(
1256 decode_gray(BigUint::from_u32(0b101).unwrap()),
1257 BigUint::from_u32(6).unwrap()
1258 );
1259 assert_eq!(
1260 decode_gray(BigUint::from_u32(0b100).unwrap()),
1261 BigUint::from_u32(7).unwrap()
1262 );
1263 }
1264
1265 #[test]
1266 fn gray_translator() {
1267 assert_eq!(
1268 GrayCodeTranslator {}
1269 .basic_translate(5, &VariableValue::BigUint(BigUint::from(0b000u32)))
1270 .0,
1271 "0"
1272 );
1273
1274 assert_eq!(
1275 GrayCodeTranslator {}
1276 .basic_translate(5, &VariableValue::BigUint(BigUint::from(0b010u32)))
1277 .0,
1278 "3"
1279 );
1280
1281 assert_eq!(
1282 GrayCodeTranslator {}
1283 .basic_translate(5, &VariableValue::String("10".to_string()))
1284 .0,
1285 "3"
1286 );
1287
1288 assert_eq!(
1289 GrayCodeTranslator {}.basic_translate(5, &VariableValue::String("-10".to_string())),
1290 ("DON'T CARE".to_string(), ValueKind::DontCare)
1291 );
1292
1293 assert_eq!(
1294 GrayCodeTranslator {}.basic_translate(5, &VariableValue::String("11h".to_string())),
1295 ("WEAK".to_string(), ValueKind::Weak)
1296 );
1297 }
1298}