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