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, 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
500#[cfg(test)]
501mod test {
502
503 use num::BigUint;
504
505 use super::*;
506
507 #[test]
508 fn group_n_chars_splits_with_remainder() {
509 assert_eq!(group_n_chars("101010", 4), vec!["10", "1010"]);
510 }
511
512 #[test]
513 fn group_n_chars_splits_evenly() {
514 assert_eq!(group_n_chars("10101010", 4), vec!["1010", "1010"]);
515 }
516
517 #[test]
518 fn group_n_chars_handles_empty_input() {
519 assert_eq!(group_n_chars("", 4), Vec::<&str>::new());
520 }
521
522 #[test]
523 fn map_to_radix_formats_binary_groups() {
524 let (formatted, kind) = map_to_radix("10000", 4, 5);
525 assert_eq!(formatted, "10");
526 assert_eq!(kind, ValueKind::Normal);
527 }
528
529 #[test]
530 fn map_to_radix_prefers_special_digits_per_group() {
531 let (formatted, kind) = map_to_radix("zx01", 4, 4);
532 assert_eq!(formatted, "x");
533 assert_eq!(kind, kind_for_binary_representation("x"));
534 }
535
536 #[test]
537 fn map_to_radix_marks_invalid_binary_digit_as_error() {
538 let (formatted, kind) = map_to_radix("1002", 4, 4);
539 assert_eq!(formatted, "?");
540 assert_eq!(kind, ValueKind::Error);
541 }
542
543 #[test]
544 fn check_wordlength_returns_yes_when_predicate_matches() {
545 let preference = check_wordlength(Some(16), |n| n.is_multiple_of(8)).unwrap();
546 assert_eq!(preference, TranslationPreference::Yes);
547 }
548
549 #[test]
550 fn check_wordlength_returns_no_for_missing_or_nonmatching_wordlength() {
551 let missing = check_wordlength(None, |n| n.is_multiple_of(8)).unwrap();
552 assert_eq!(missing, TranslationPreference::No);
553
554 let nonmatching = check_wordlength(Some(7), |n| n.is_multiple_of(8)).unwrap();
555 assert_eq!(nonmatching, TranslationPreference::No);
556 }
557
558 #[test]
559 fn decode_lebxxx_decodes_valid_value() {
560 let decoded = decode_lebxxx(&BigUint::from(0b01011010_11101111u16)).unwrap();
561 assert_eq!(decoded, BigUint::from(11_631u32));
562 }
563
564 #[test]
565 fn decode_lebxxx_rejects_invalid_msb() {
566 let err = decode_lebxxx(&BigUint::from(0b10000000u8)).unwrap_err();
567 assert_eq!(err, "invalid MSB");
568 }
569
570 #[test]
571 fn hexadecimal_translation_groups_digits_correctly_string() {
572 assert_eq!(
573 HexTranslator {}
574 .basic_translate(5, &VariableValue::String("10000".to_string()))
575 .0,
576 "10"
577 );
578
579 assert_eq!(
580 HexTranslator {}
581 .basic_translate(5, &VariableValue::String("1000".to_string()))
582 .0,
583 "08"
584 );
585
586 assert_eq!(
587 HexTranslator {}
588 .basic_translate(5, &VariableValue::String("100000".to_string()))
589 .0,
590 "20"
591 );
592 assert_eq!(
593 HexTranslator {}
594 .basic_translate(10, &VariableValue::String("1z00x0".to_string()))
595 .0,
596 "0zx"
597 );
598 assert_eq!(
599 HexTranslator {}
600 .basic_translate(10, &VariableValue::String("z0110".to_string()))
601 .0,
602 "zz6"
603 );
604 assert_eq!(
605 HexTranslator {}
606 .basic_translate(24, &VariableValue::String("xz0110".to_string()))
607 .0,
608 "xxxxx6"
609 );
610 }
611
612 #[test]
613 fn hexadecimal_translation_groups_digits_correctly_bigint() {
614 assert_eq!(
615 HexTranslator {}
616 .basic_translate(5, &VariableValue::BigUint(BigUint::from(0b10000u32)))
617 .0,
618 "10"
619 );
620 assert_eq!(
621 HexTranslator {}
622 .basic_translate(5, &VariableValue::BigUint(BigUint::from(0b1000u32)))
623 .0,
624 "08"
625 );
626 assert_eq!(
627 HexTranslator {}
628 .basic_translate(5, &VariableValue::BigUint(BigUint::from(0u32)))
629 .0,
630 "00"
631 );
632 }
633
634 #[test]
635 fn octal_translation_groups_digits_correctly_string() {
636 assert_eq!(
637 OctalTranslator {}
638 .basic_translate(5, &VariableValue::String("10000".to_string()))
639 .0,
640 "20"
641 );
642 assert_eq!(
643 OctalTranslator {}
644 .basic_translate(5, &VariableValue::String("100".to_string()))
645 .0,
646 "04"
647 );
648 assert_eq!(
649 OctalTranslator {}
650 .basic_translate(9, &VariableValue::String("x100".to_string()))
651 .0,
652 "xx4"
653 );
654 }
655
656 #[test]
657 fn octal_translation_groups_digits_correctly_bigint() {
658 assert_eq!(
659 OctalTranslator {}
660 .basic_translate(5, &VariableValue::BigUint(BigUint::from(0b10000u32)))
661 .0,
662 "20"
663 );
664 assert_eq!(
665 OctalTranslator {}
666 .basic_translate(5, &VariableValue::BigUint(BigUint::from(0b00100u32)))
667 .0,
668 "04"
669 );
670 }
671
672 #[test]
673 fn grouping_binary_translation_groups_digits_correctly_string() {
674 assert_eq!(
675 GroupingBinaryTranslator {}
676 .basic_translate(5, &VariableValue::String("1000w".to_string()))
677 .0,
678 "1 000w"
679 );
680 assert_eq!(
681 GroupingBinaryTranslator {}
682 .basic_translate(8, &VariableValue::String("100l00".to_string()))
683 .0,
684 "0010 0l00"
685 );
686 assert_eq!(
687 GroupingBinaryTranslator {}
688 .basic_translate(7, &VariableValue::String("10x00".to_string()))
689 .0,
690 "001 0x00"
691 );
692 assert_eq!(
693 GroupingBinaryTranslator {}
694 .basic_translate(7, &VariableValue::String("z10x00".to_string()))
695 .0,
696 "zz1 0x00"
697 );
698 }
699
700 #[test]
701 fn grouping_binary_translation_groups_digits_correctly_bigint() {
702 assert_eq!(
703 GroupingBinaryTranslator {}
704 .basic_translate(7, &VariableValue::BigUint(BigUint::from(0b100000u32)))
705 .0,
706 "010 0000"
707 );
708 }
709
710 #[test]
711 fn binary_translation_groups_digits_correctly_string() {
712 assert_eq!(
713 BinaryTranslator {}
714 .basic_translate(5, &VariableValue::String("10000".to_string()))
715 .0,
716 "10000"
717 );
718 assert_eq!(
719 BinaryTranslator {}
720 .basic_translate(8, &VariableValue::String("100h00".to_string()))
721 .0,
722 "00100h00"
723 );
724 assert_eq!(
725 BinaryTranslator {}
726 .basic_translate(7, &VariableValue::String("10x0-".to_string()))
727 .0,
728 "0010x0-"
729 );
730 assert_eq!(
731 BinaryTranslator {}
732 .basic_translate(7, &VariableValue::String("z10x00".to_string()))
733 .0,
734 "zz10x00"
735 );
736 }
737
738 #[test]
739 fn binary_translation_groups_digits_correctly_bigint() {
740 assert_eq!(
741 BinaryTranslator {}
742 .basic_translate(7, &VariableValue::BigUint(BigUint::from(0b100000u32)))
743 .0,
744 "0100000"
745 );
746 }
747
748 #[test]
749 fn ascii_translation_from_biguint() {
750 assert_eq!(
751 ASCIITranslator {}
752 .basic_translate(
753 15,
754 &VariableValue::BigUint(BigUint::from(0b100111101001011u32))
755 )
756 .0,
757 "OK"
758 );
759 assert_eq!(
760 ASCIITranslator {}
761 .basic_translate(72, &VariableValue::BigUint(BigUint::from(0b010011000110111101101110011001110010000001110100011001010111001101110100u128)))
762 .0,
763 "Long test"
764 );
765 }
766
767 #[test]
768 fn ascii_translation_from_string() {
769 assert_eq!(
770 ASCIITranslator {}
771 .basic_translate(15, &VariableValue::String("100111101001011".to_string()))
772 .0,
773 "OK"
774 );
775 assert_eq!(
776 ASCIITranslator {}
777 .basic_translate(
778 72,
779 &VariableValue::String(
780 "010011000110111101101110011001110010000001110100011001010111001101110100"
781 .to_string()
782 )
783 )
784 .0,
785 "Long test"
786 );
787 assert_eq!(
788 ASCIITranslator {}
789 .basic_translate(16, &VariableValue::String("010x111101001011".to_string()))
790 .0,
791 "UNDEF"
792 );
793 assert_eq!(
795 ASCIITranslator {}
796 .basic_translate(15, &VariableValue::String("11000001001011".to_string()))
797 .0,
798 "0K"
799 );
800 }
801
802 #[test]
803 fn bit_translation_from_biguint() {
804 assert_eq!(
805 BitTranslator {}
806 .basic_translate(1, &VariableValue::BigUint(BigUint::from(0b1u8)))
807 .0,
808 "1"
809 );
810 assert_eq!(
811 BitTranslator {}
812 .basic_translate(1, &VariableValue::BigUint(BigUint::from(0b0u8)))
813 .0,
814 "0"
815 );
816 }
817
818 #[test]
819 fn bit_translation_from_string() {
820 assert_eq!(
821 BitTranslator {}
822 .basic_translate(1, &VariableValue::String("1".to_string()))
823 .0,
824 "1"
825 );
826 assert_eq!(
827 BitTranslator {}
828 .basic_translate(1, &VariableValue::String("0".to_string()))
829 .0,
830 "0"
831 );
832 assert_eq!(
833 BitTranslator {}
834 .basic_translate(1, &VariableValue::String("x".to_string()))
835 .0,
836 "x"
837 );
838 }
839
840 #[test]
841 fn bit_translator_with_invalid_data() {
842 assert_eq!(
843 BitTranslator {}
844 .basic_translate(2, &VariableValue::BigUint(BigUint::from(3u8)))
845 .0,
846 "-"
847 );
848 }
849
850 #[test]
851 fn leb_translation_from_biguint() {
852 assert_eq!(
853 LebTranslator {}
854 .basic_translate(16, &VariableValue::BigUint(0b01011010_11101111u16.into()))
855 .0,
856 "11631"
857 );
858 assert_eq!(
859 LebTranslator {}
860 .basic_translate(16, &VariableValue::BigUint(0b00000000_00000001u16.into()))
861 .0,
862 "1"
863 );
864 assert_eq!(
865 LebTranslator{}.basic_translate(64, &VariableValue::BigUint(0b01001010_11110111_11101000_10100000_10111010_11110110_11100001_10011001u64.into())).0, "42185246214303897"
866 );
867 }
868 #[test]
869 fn leb_translation_from_string() {
870 assert_eq!(
871 LebTranslator {}
872 .basic_translate(16, &VariableValue::String("0111110011100010".to_owned()))
873 .0,
874 "15970"
875 );
876 }
877 #[test]
878 fn leb_translation_invalid_msb() {
879 assert_eq!(
880 LebTranslator {}
881 .basic_translate(16, &VariableValue::BigUint(0b1000000010000000u16.into()))
882 .0,
883 "invalid MSB: 1000 0000 1000 0000"
884 );
885 }
886 #[test]
887 fn leb_translation_invalid_continuation() {
888 assert_eq!(
889 LebTranslator {}
890 .basic_translate(16, &VariableValue::BigUint(0b0111111101111111u16.into()))
891 .0,
892 "invalid flag: 0111 1111 0111 1111"
893 );
894 }
895
896 #[test]
897 fn leb_tranlator_input_not_multiple_of_8() {
898 assert_eq!(
900 LebTranslator {}
901 .basic_translate(16, &VariableValue::BigUint(0b00001111111u16.into()))
902 .0,
903 "127"
904 );
905 }
906
907 #[test]
908 fn number_of_ones_translation_string() {
909 assert_eq!(
910 NumberOfOnesTranslator {}
911 .basic_translate(5, &VariableValue::String("10000".to_string()))
912 .0,
913 "1"
914 );
915 assert_eq!(
916 NumberOfOnesTranslator {}
917 .basic_translate(5, &VariableValue::String("101".to_string()))
918 .0,
919 "2"
920 );
921 assert_eq!(
922 NumberOfOnesTranslator {}
923 .basic_translate(9, &VariableValue::String("1x100".to_string()))
924 .0,
925 "2"
926 );
927 }
928
929 #[test]
930 fn number_of_ones_translation_bigint() {
931 assert_eq!(
932 NumberOfOnesTranslator {}
933 .basic_translate(17, &VariableValue::BigUint(BigUint::from(0b101110000u32)))
934 .0,
935 "4"
936 );
937 assert_eq!(
938 NumberOfOnesTranslator {}
939 .basic_translate(40, &VariableValue::BigUint(BigUint::from(0b00100u32)))
940 .0,
941 "1"
942 );
943 }
944
945 #[test]
946 fn trailing_ones_translation_string() {
947 assert_eq!(
948 TrailingOnesTranslator {}
949 .basic_translate(5, &VariableValue::String("10111".to_string()))
950 .0,
951 "3"
952 );
953 assert_eq!(
954 TrailingOnesTranslator {}
955 .basic_translate(5, &VariableValue::String("101".to_string()))
956 .0,
957 "1"
958 );
959 assert_eq!(
960 TrailingOnesTranslator {}
961 .basic_translate(9, &VariableValue::String("x100".to_string()))
962 .0,
963 "0"
964 );
965 }
966
967 #[test]
968 fn trailing_ones_translation_bigint() {
969 assert_eq!(
970 TrailingOnesTranslator {}
971 .basic_translate(17, &VariableValue::BigUint(BigUint::from(0b101111111u32)))
972 .0,
973 "7"
974 );
975 assert_eq!(
976 TrailingOnesTranslator {}
977 .basic_translate(40, &VariableValue::BigUint(BigUint::from(0b00100u32)))
978 .0,
979 "0"
980 );
981 assert_eq!(
982 TrailingOnesTranslator {}
983 .basic_translate(5, &VariableValue::BigUint(BigUint::from(0b11111u32)))
984 .0,
985 "5"
986 );
987 }
988
989 #[test]
990 fn trailing_zeros_translation_string() {
991 assert_eq!(
992 TrailingZerosTranslator {}
993 .basic_translate(5, &VariableValue::String("10000".to_string()))
994 .0,
995 "4"
996 );
997 assert_eq!(
998 TrailingZerosTranslator {}
999 .basic_translate(5, &VariableValue::String("101".to_string()))
1000 .0,
1001 "0"
1002 );
1003 assert_eq!(
1004 TrailingZerosTranslator {}
1005 .basic_translate(9, &VariableValue::String("x100".to_string()))
1006 .0,
1007 "2"
1008 );
1009 }
1010
1011 #[test]
1012 fn trailing_zeros_translation_bigint() {
1013 assert_eq!(
1014 TrailingZerosTranslator {}
1015 .basic_translate(17, &VariableValue::BigUint(BigUint::from(0b101111111u32)))
1016 .0,
1017 "0"
1018 );
1019 assert_eq!(
1020 TrailingZerosTranslator {}
1021 .basic_translate(40, &VariableValue::BigUint(BigUint::from(0b00100u32)))
1022 .0,
1023 "2"
1024 );
1025 assert_eq!(
1026 TrailingZerosTranslator {}
1027 .basic_translate(16, &VariableValue::BigUint(BigUint::from(0b0u32)))
1028 .0,
1029 "16"
1030 );
1031 }
1032
1033 #[test]
1034 fn leading_ones_translation_string() {
1035 assert_eq!(
1036 LeadingOnesTranslator {}
1037 .basic_translate(5, &VariableValue::String("11101".to_string()))
1038 .0,
1039 "3"
1040 );
1041 assert_eq!(
1042 LeadingOnesTranslator {}
1043 .basic_translate(5, &VariableValue::String("101".to_string()))
1044 .0,
1045 "0"
1046 );
1047 assert_eq!(
1048 LeadingOnesTranslator {}
1049 .basic_translate(9, &VariableValue::String("x100".to_string()))
1050 .0,
1051 "0"
1052 );
1053 }
1054
1055 #[test]
1056 fn leading_ones_translation_bigint() {
1057 assert_eq!(
1058 LeadingOnesTranslator {}
1059 .basic_translate(11, &VariableValue::BigUint(BigUint::from(0b11111111100u32)))
1060 .0,
1061 "9"
1062 );
1063 assert_eq!(
1064 LeadingOnesTranslator {}
1065 .basic_translate(40, &VariableValue::BigUint(BigUint::from(0b00100u32)))
1066 .0,
1067 "0"
1068 );
1069 assert_eq!(
1070 LeadingOnesTranslator {}
1071 .basic_translate(5, &VariableValue::BigUint(BigUint::from(0b11111u32)))
1072 .0,
1073 "5"
1074 );
1075 }
1076
1077 #[test]
1078 fn leading_zeros_translation_string() {
1079 assert_eq!(
1080 LeadingZerosTranslator {}
1081 .basic_translate(5, &VariableValue::String("10000".to_string()))
1082 .0,
1083 "0"
1084 );
1085 assert_eq!(
1086 LeadingZerosTranslator {}
1087 .basic_translate(5, &VariableValue::String("101".to_string()))
1088 .0,
1089 "2"
1090 );
1091 assert_eq!(
1092 LeadingZerosTranslator {}
1093 .basic_translate(9, &VariableValue::String("x100".to_string()))
1094 .0,
1095 "0"
1096 );
1097 }
1098
1099 #[test]
1100 fn leading_zeros_translation_bigint() {
1101 assert_eq!(
1102 LeadingZerosTranslator {}
1103 .basic_translate(17, &VariableValue::BigUint(BigUint::from(0b101111111u32)))
1104 .0,
1105 "8"
1106 );
1107 assert_eq!(
1108 LeadingZerosTranslator {}
1109 .basic_translate(40, &VariableValue::BigUint(BigUint::from(0b00100u32)))
1110 .0,
1111 "37"
1112 );
1113 assert_eq!(
1114 LeadingZerosTranslator {}
1115 .basic_translate(16, &VariableValue::BigUint(BigUint::from(0b0u32)))
1116 .0,
1117 "16"
1118 );
1119 }
1120
1121 #[test]
1122 fn signbits_translation_string() {
1123 assert_eq!(
1124 IdenticalMSBsTranslator {}
1125 .basic_translate(5, &VariableValue::String("10000".to_string()))
1126 .0,
1127 "1"
1128 );
1129 assert_eq!(
1130 IdenticalMSBsTranslator {}
1131 .basic_translate(7, &VariableValue::String("0".to_string()))
1132 .0,
1133 "7"
1134 );
1135 assert_eq!(
1136 IdenticalMSBsTranslator {}
1137 .basic_translate(5, &VariableValue::String("101".to_string()))
1138 .0,
1139 "2"
1140 );
1141 assert_eq!(
1142 IdenticalMSBsTranslator {}
1143 .basic_translate(9, &VariableValue::String("x100".to_string()))
1144 .0,
1145 "0"
1146 );
1147 assert_eq!(
1148 IdenticalMSBsTranslator {}
1149 .basic_translate(5, &VariableValue::String("11101".to_string()))
1150 .0,
1151 "3"
1152 );
1153 }
1154
1155 #[test]
1156 fn signbits_translation_bigint() {
1157 assert_eq!(
1158 IdenticalMSBsTranslator {}
1159 .basic_translate(17, &VariableValue::BigUint(BigUint::from(0b101111111u32)))
1160 .0,
1161 "8"
1162 );
1163 assert_eq!(
1164 IdenticalMSBsTranslator {}
1165 .basic_translate(40, &VariableValue::BigUint(BigUint::from(0b00100u32)))
1166 .0,
1167 "37"
1168 );
1169 assert_eq!(
1170 IdenticalMSBsTranslator {}
1171 .basic_translate(16, &VariableValue::BigUint(BigUint::from(0b0u32)))
1172 .0,
1173 "16"
1174 );
1175 assert_eq!(
1176 IdenticalMSBsTranslator {}
1177 .basic_translate(11, &VariableValue::BigUint(BigUint::from(0b11111111100u32)))
1178 .0,
1179 "9"
1180 );
1181 assert_eq!(
1182 IdenticalMSBsTranslator {}
1183 .basic_translate(5, &VariableValue::BigUint(BigUint::from(0b11111u32)))
1184 .0,
1185 "5"
1186 );
1187 }
1188}