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