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