radio_datetime_utils/
radio_datetime_helpers.rs

1// SPDX-License-Identifier: MIT OR Apache-2.0
2// Copyright 2023-2025 René Ladan <rene0+codeberg@freedom.nl>
3
4use crate::BIT_BUFFER_SIZE;
5use heapless::Vec;
6
7/// Maximum BCD value that can safely be encoded in an u32
8const MAX_BCD_VALUE: u32 = 3_999_999_999;
9/// Number of BCD bits needed to represent `MAX_BCD_VALUE`
10const MAX_BCD_LENGTH: usize = 38;
11
12/// Return the difference in microseconds between two timestamps.
13///
14/// This function takes wrapping of the parameters into account,
15/// as they are u32, so they wrap each 71m35.
16///
17/// # Arguments
18/// * `t0` - old timestamp in microseconds
19/// * `t1` - new timestamp in microseconds
20pub fn time_diff(t0: u32, t1: u32) -> u32 {
21    if t1 >= t0 {
22        t1 - t0
23    } else if t0 > 0 {
24        u32::MAX - t0 + t1 + 1 // wrapped, each 1h11m35s
25    } else {
26        0 // cannot happen, because t1 < t0 && t0 == 0, but prevents E0317 (missing else clause)
27    }
28}
29
30/// Increase or wrap the passed second counter.
31///
32/// Returns if the second counter was increased/wrapped normally (true)
33/// or due to an overflow (false).
34///
35/// # Arguments
36/// * `second` - the value of the current second (so normally 0..59)
37/// * `new_minute` - whether a new minute arrived
38/// * `minute_length` - the length of this minute in seconds
39pub fn increase_second(second: &mut u8, new_minute: bool, minute_length: u8) -> bool {
40    if new_minute {
41        *second = 0;
42        true
43    } else {
44        *second += 1;
45        // wrap in case we missed the minute marker to prevent index-out-of-range
46        if *second == minute_length || (*second as usize) == BIT_BUFFER_SIZE {
47            *second = 0;
48            false
49        } else {
50            true
51        }
52    }
53}
54
55#[deprecated(
56    since = "1.2.0",
57    note = "please use `decode_bcd()` instead which can decode larger values"
58)]
59pub fn get_bcd_value(bit_buffer: &[Option<bool>], start: usize, stop: usize) -> Option<u8> {
60    let (p0, p1) = min_max(start, stop);
61    if p1 - p0 >= 8 {
62        return None; // legacy test
63    }
64    decode_bcd(bit_buffer, start, stop).map(|v| v as u8)
65}
66
67/// Returns the BCD-encoded value of the given buffer over the given range,
68/// or None if the input is invalid.
69///
70/// # Arguments
71/// * `bit_buffer` - buffer containing the bits (maximum `MAX_BCD_LENGTH` bits)
72/// * `start` - start bit position (least significant)
73/// * `stop` - stop bit position (most significant)
74pub fn decode_bcd(bit_buffer: &[Option<bool>], start: usize, stop: usize) -> Option<u32> {
75    let (p0, p1) = min_max(start, stop);
76    if p1 - p0 >= MAX_BCD_LENGTH {
77        return None;
78    }
79    let v = prepare_vector(bit_buffer, p0, p1, stop < start)?;
80    let mut res_bcd = 0;
81    let mut this_bcd = 0;
82    let mut count = 0;
83    let mut index = 0;
84    let mut mult = 1;
85    for bit in v {
86        this_bcd += (1 << index) * bit as u32;
87        index += 1;
88        count += 1;
89        if count != 0 && count % 4 == 0 {
90            if this_bcd > 9 {
91                return None;
92            }
93            res_bcd += mult * this_bcd;
94            mult *= 10;
95            this_bcd = 0;
96            index = 0;
97        }
98    }
99    Some(res_bcd + mult * this_bcd)
100}
101
102/// Encodes an u32 as a BCD vector of the given length.
103///
104/// # Arguments
105/// * `value` - the u32 value to encode, up to `MAX_BCD_VALUE`
106/// * `length` - the desired length of the BCD vector.
107/// * `msb_first` - add the most significant bit first instead of the least significant bit.
108pub fn encode_bcd(value: u32, length: u8, msb_first: bool) -> Vec<bool, MAX_BCD_LENGTH> {
109    let mut v = Vec::new();
110    if length == 0 || length > MAX_BCD_LENGTH as u8 || value > MAX_BCD_VALUE {
111        return v; // empty vector
112    }
113    let mut div = 1;
114    let mut index = 0;
115    let mut val = value % 10;
116    for count in 0..length {
117        if count != 0 && count % 4 == 0 {
118            div *= 10;
119            val = (value / div) % 10;
120            index = 0;
121        }
122        v.push(val & (1 << index) != 0).unwrap();
123        index += 1;
124    }
125    if msb_first {
126        v.reverse()
127    };
128    v
129}
130
131#[deprecated(
132    since = "1.2.0",
133    note = "Use decode_parity() instead to avoid confusion with encode_parity()"
134)]
135pub fn get_parity(
136    bit_buffer: &[Option<bool>],
137    start: usize,
138    stop: usize,
139    parity: Option<bool>,
140) -> Option<bool> {
141    decode_parity(bit_buffer, start, stop, parity)
142}
143
144/// Returns parity of the given buffer over the given range, or None if the input is invalid.
145/// Should be Some(false) for even parity and Some(true) for odd parity.
146///
147/// # Arguments
148/// * `bit_buffer` - buffer containing the bits to check.
149/// * `start` - start bit position
150/// * `stop` - stop bit position
151/// * `parity` - parity bit value
152pub fn decode_parity(
153    bit_buffer: &[Option<bool>],
154    start: usize,
155    stop: usize,
156    parity: Option<bool>,
157) -> Option<bool> {
158    parity?;
159    let mut s_parity = parity.unwrap();
160    let (p0, p1) = min_max(start, stop);
161    for bit in &bit_buffer[p0..=p1] {
162        (*bit)?;
163        s_parity ^= bit.unwrap();
164    }
165    Some(s_parity)
166}
167
168/// Calculates the parity value of the given buffer depending on whether the parity is even or odd.
169///
170/// # Arguments
171/// * `bit_buffer` - buffer containing the bits to calculate the parity of
172/// * `even` - if the parity is even or odd
173pub fn encode_parity(bit_buffer: &[bool], even: bool) -> bool {
174    let mut parity = even;
175    for bit in bit_buffer {
176        parity ^= bit;
177    }
178    !parity
179}
180
181/// Returns the binary-encoded value of the given buffer over the given range,
182/// or None if the input is invalid.
183///
184/// # Arguments
185/// * `bit_buffer` - buffer containing the bits (maximum 32 bits)
186/// * `start` - start bit position (least significant)
187/// * `stop` - stop bit position (most significant)
188pub fn decode_bin(bit_buffer: &[Option<bool>], start: usize, stop: usize) -> Option<u32> {
189    let (p0, p1) = min_max(start, stop);
190    if p1 - p0 >= 32 {
191        return None;
192    }
193    let v = prepare_vector(bit_buffer, p0, p1, stop < start)?;
194    let mut val = 0;
195    let mut mult = 1;
196    for b in v {
197        val += mult * b as u32;
198        // avoid overflow panic
199        if mult < 0x8000_0000 {
200            mult *= 2;
201        }
202    }
203    Some(val)
204}
205
206/// Encodes an u32 as a binary vector of the given length.
207///
208/// # Arguments
209/// * `value` - the u32 value to encode, up to 4 Gi
210/// * `length` - the desired length of the binary vector, up to 32.
211/// * `msb_first` - add the most significant bit first instead of the least significant bit.
212pub fn encode_bin(value: u32, length: u8, msb_first: bool) -> Vec<bool, 32> {
213    let mut v = Vec::new();
214    if length == 0 || length > 32 {
215        return v; // empty vector
216    }
217    for index in 0..length {
218        v.push(value & (1 << index) != 0).unwrap();
219    }
220    if msb_first {
221        v.reverse()
222    };
223    v
224}
225
226/// Decode the unary value (a single hexadecimal digit) of the given slice.
227/// A 0 bit cannot be followed by a 1 bit.
228///
229/// # Arguments
230/// * `bit_buffer` - buffer containing to calculate the value from
231/// * `start` - start bit position
232/// * `stop` - stop bit position
233pub fn decode_unary(bit_buffer: &[Option<bool>], start: usize, stop: usize) -> Option<u8> {
234    let (p0, p1) = min_max(start, stop);
235    if p1 - p0 >= 15 {
236        return None;
237    }
238    let v = prepare_vector(bit_buffer, p0, p1, stop < start)?;
239    let mut sum = 0;
240    let mut old_bit = None;
241    for bit in v {
242        if bit && old_bit == Some(false) {
243            return None;
244        }
245        sum += bit as u8;
246        old_bit = Some(bit);
247    }
248    Some(sum)
249}
250
251/// Encodes an u8 as a unary vector of te given length.
252///
253/// # Arguments
254/// * `value` - the u32 value to encode, 0..15 (a single hexadecimal digit)
255/// * `length` - the desired length of the binary vector, up to 15.
256/// * `msb_first` - add the most significant bit first instead of the least significant bit.
257pub fn encode_unary(value: u8, length: u8, msb_first: bool) -> Vec<bool, 15> {
258    let mut v = Vec::new();
259    if length == 0 || length > 15 {
260        return v; //empty vector
261    }
262    for index in 0..length {
263        v.push(index < value).unwrap();
264    }
265    if msb_first {
266        v.reverse();
267    }
268    v
269}
270
271/// Returns the given buffer, optionally reversed, or None if it contains None values.
272///
273/// # Arguments
274/// * `bit_buffer` - the bit buffer
275/// * `p0` - minimum of the start and stop positions
276/// * `p1`-  maximum of the start and stop positions
277/// * `reversed` - if the buffer needs to be reversed.
278fn prepare_vector(
279    bit_buffer: &[Option<bool>],
280    p0: usize,
281    p1: usize,
282    reversed: bool,
283) -> Option<Vec<bool, MAX_BCD_LENGTH>> {
284    let mut v: Vec<bool, MAX_BCD_LENGTH> = Vec::new();
285    for bit in &bit_buffer[p0..=p1] {
286        (*bit)?;
287        v.push(bit.unwrap()).unwrap();
288    }
289    if reversed {
290        v.reverse();
291    }
292    Some(v)
293}
294
295/// Return a tuple of the two parameters in ascending order.
296///
297/// # Arguments
298/// * `a` - first argument
299/// * `b` - second argument
300fn min_max(a: usize, b: usize) -> (usize, usize) {
301    if a < b { (a, b) } else { (b, a) }
302}
303
304#[cfg(test)]
305mod tests {
306    use super::*;
307
308    #[test]
309    fn test_single_bit_vector_none() {
310        assert_eq!(prepare_vector(&[None], 0, 0, false), None);
311    }
312
313    #[test]
314    fn test_single_bit_vector_none_rev() {
315        assert_eq!(prepare_vector(&[None], 0, 0, true), None);
316    }
317
318    #[test]
319    fn test_single_bit_vector_some() {
320        let mut v: Vec<bool, MAX_BCD_LENGTH> = Vec::new();
321        v.push(true).unwrap();
322        assert_eq!(prepare_vector(&[Some(true)], 0, 0, false), Some(v));
323    }
324
325    #[test]
326    fn test_single_bit_vector_some_rev() {
327        let mut v: Vec<bool, MAX_BCD_LENGTH> = Vec::new();
328        v.push(true).unwrap();
329        assert_eq!(prepare_vector(&[Some(true)], 0, 0, true), Some(v));
330    }
331
332    #[test]
333    fn test_two_bits_vector() {
334        let mut v: Vec<bool, MAX_BCD_LENGTH> = Vec::new();
335        v.push(false).unwrap();
336        v.push(true).unwrap();
337        assert_eq!(
338            prepare_vector(&[Some(false), Some(true)], 0, 1, false),
339            Some(v)
340        );
341    }
342
343    #[test]
344    fn test_two_bits_vector_rev() {
345        let mut v: Vec<bool, MAX_BCD_LENGTH> = Vec::new();
346        v.push(true).unwrap();
347        v.push(false).unwrap();
348        assert_eq!(
349            prepare_vector(&[Some(false), Some(true)], 0, 1, true),
350            Some(v)
351        );
352    }
353
354    #[test]
355    fn test_time_diff_difference_1() {
356        assert_eq!(time_diff(2, 3), 1);
357    }
358
359    #[test]
360    fn test_time_diff_difference_3() {
361        assert_eq!(time_diff(0, 3), 3);
362    }
363
364    #[test]
365    fn test_time_diff_flipped_m100_0() {
366        assert_eq!(time_diff(u32::MAX - 100, 0), 101);
367    }
368
369    #[test]
370    fn test_time_diff_flipped_m100_100() {
371        assert_eq!(time_diff(u32::MAX - 100, 100), 201);
372    }
373
374    #[test]
375    fn test_time_diff_zero() {
376        assert_eq!(time_diff(2, 2), 0);
377    }
378
379    const BIT_BUFFER: [Option<bool>; 10] = [
380        Some(false),
381        Some(true),
382        Some(false),
383        Some(false),
384        Some(true),
385        Some(true),
386        Some(true),
387        Some(true),
388        None,
389        Some(false),
390    ];
391
392    const BITS_99: [Option<bool>; 8] = [
393        Some(true),
394        Some(false),
395        Some(false),
396        Some(true),
397        Some(true),
398        Some(false),
399        Some(false),
400        Some(true),
401    ];
402
403    #[test]
404    fn test_increase_second_regular() {
405        let mut second = 54;
406        assert_eq!(increase_second(&mut second, false, 60), true);
407        assert_eq!(second, 55);
408    }
409
410    #[test]
411    fn test_increase_second_new_minute() {
412        let mut second = 54; // can be less than minute_length-1 during the first partial minute
413        assert_eq!(increase_second(&mut second, true, 60), true);
414        assert_eq!(second, 0);
415    }
416
417    #[test]
418    fn test_increase_second_overflow_minute_length_hit() {
419        let mut second = 59;
420        assert_eq!(increase_second(&mut second, false, 60), false);
421        assert_eq!(second, 0);
422    }
423
424    #[test]
425    #[should_panic] // caller is lagging, this should never happen
426    fn test_increase_second_overflow_minute_length_over() {
427        let mut second = 60;
428        assert_eq!(increase_second(&mut second, false, 60), false);
429        assert_eq!(second, 0);
430    }
431
432    #[test]
433    fn test_increase_second_overflow_buffer_hit() {
434        let mut second = (BIT_BUFFER_SIZE - 1) as u8;
435        assert_eq!(increase_second(&mut second, false, 60), false);
436        assert_eq!(second, 0);
437    }
438
439    #[test]
440    #[should_panic] // caller is lagging, this should never happen
441    fn test_increase_second_overflow_buffer_over() {
442        let mut second = BIT_BUFFER_SIZE as u8;
443        assert_eq!(increase_second(&mut second, false, 60), false);
444        assert_eq!(second, 0);
445    }
446
447    #[test]
448    fn ok_decode_bcd_regular() {
449        assert_eq!(decode_bcd(&BIT_BUFFER[0..=4], 0, 4), Some(12));
450    }
451
452    #[deprecated]
453    #[test]
454    fn legacy_get_bcd_value_regular() {
455        assert_eq!(get_bcd_value(&BIT_BUFFER[0..=4], 0, 4), Some(12));
456    }
457
458    #[test]
459    fn ok_decode_bcd_single_bit() {
460        assert_eq!(decode_bcd(&BIT_BUFFER[1..=1], 0, 0), Some(1));
461        // single-bit value, must be a slice
462    }
463
464    #[deprecated]
465    #[test]
466    fn legacy_ok_get_bcd_value_single_bit() {
467        assert_eq!(get_bcd_value(&BIT_BUFFER[1..=1], 0, 0), Some(1));
468        // single-bit value, must be a slice
469    }
470
471    #[test]
472    fn bad_decode_bcd_too_large_total_bcd_lsb() {
473        assert_eq!(decode_bcd(&BIT_BUFFER[0..=7], 0, 7), None);
474    }
475
476    #[test]
477    fn bad_decode_bcd_too_large_total_bcd_msb() {
478        assert_eq!(decode_bcd(&BIT_BUFFER[0..=7], 7, 0), None);
479    }
480
481    #[deprecated]
482    #[test]
483    fn legacy_bad_get_bcd_value_too_large_total_bcd() {
484        assert_eq!(get_bcd_value(&BIT_BUFFER[0..=7], 0, 7), None);
485    }
486
487    #[test]
488    fn bad_decode_bcd_too_large_single_bcd() {
489        assert_eq!(decode_bcd(&BIT_BUFFER[4..=7], 0, 3), None);
490    }
491
492    #[deprecated]
493    #[test]
494    fn legacy_bad_get_bcd_value_too_large_single_bcd() {
495        assert_eq!(get_bcd_value(&BIT_BUFFER[4..=7], 0, 3), None);
496    }
497
498    #[test]
499    fn bad_decode_bcd_none() {
500        assert_eq!(decode_bcd(&BIT_BUFFER[7..=9], 0, 2), None);
501    }
502
503    #[deprecated]
504    #[test]
505    fn legacy_bad_get_bcd_value_none() {
506        assert_eq!(get_bcd_value(&BIT_BUFFER[7..=9], 0, 2), None);
507    }
508
509    #[deprecated]
510    #[test]
511    fn legacy_bad_get_bcd_value_too_wide() {
512        assert_eq!(get_bcd_value(&BIT_BUFFER, 0, 9), None);
513    }
514
515    // decode_bcd() cannot operate on an empty slice because it always makes one iteration
516
517    #[test]
518    fn bad_decode_bcd_too_wide() {
519        assert_eq!(
520            decode_bcd(&[Some(false); MAX_BCD_LENGTH + 1], 0, MAX_BCD_LENGTH + 1),
521            None
522        );
523    }
524
525    #[test]
526    fn ok_decode_bcd_backwards() {
527        assert_eq!(decode_bcd(&BIT_BUFFER[0..=5], 5, 0), Some(13));
528    }
529
530    #[deprecated]
531    #[test]
532    fn legacy_ok_get_bcd_value_backwards() {
533        assert_eq!(get_bcd_value(&BIT_BUFFER[0..=5], 5, 0), Some(13));
534    }
535
536    #[test]
537    fn ok_decode_bcd_99_lsb() {
538        assert_eq!(decode_bcd(&BITS_99, 0, 7), Some(99));
539    }
540
541    #[deprecated]
542    #[test]
543    fn legacy_ok_get_bcd_value_99_lsb() {
544        assert_eq!(get_bcd_value(&BITS_99, 0, 7), Some(99));
545    }
546
547    #[test]
548    fn ok_decode_bcd_99_msb() {
549        assert_eq!(decode_bcd(&BITS_99, 7, 0), Some(99));
550    }
551
552    #[deprecated]
553    #[test]
554    fn legacy_ok_get_bcd_value_99_msb() {
555        assert_eq!(get_bcd_value(&BITS_99, 7, 0), Some(99));
556    }
557
558    #[test]
559    fn ok_decode_bcd_399_lsb() {
560        const BITS_399_LSB: [Option<bool>; 10] = [
561            Some(true),
562            Some(false),
563            Some(false),
564            Some(true),
565            Some(true),
566            Some(false),
567            Some(false),
568            Some(true),
569            Some(true),
570            Some(true),
571        ];
572        assert_eq!(decode_bcd(&BITS_399_LSB, 0, 9), Some(399));
573    }
574
575    #[test]
576    fn ok_decode_bcd_399_msb() {
577        const BITS_399_MSB: [Option<bool>; 10] = [
578            Some(true),
579            Some(true),
580            Some(true),
581            Some(false),
582            Some(false),
583            Some(true),
584            Some(true),
585            Some(false),
586            Some(false),
587            Some(true),
588        ];
589        assert_eq!(decode_bcd(&BITS_399_MSB, 9, 0), Some(399));
590    }
591
592    #[test]
593    fn ok_decode_bcd_max_lsb() {
594        const BITS_MAX_LSB: [Option<bool>; MAX_BCD_LENGTH] = [
595            Some(true),
596            Some(false),
597            Some(false),
598            Some(true),
599            Some(true),
600            Some(false),
601            Some(false),
602            Some(true),
603            Some(true),
604            Some(false),
605            Some(false),
606            Some(true),
607            Some(true),
608            Some(false),
609            Some(false),
610            Some(true),
611            Some(true),
612            Some(false),
613            Some(false),
614            Some(true),
615            Some(true),
616            Some(false),
617            Some(false),
618            Some(true),
619            Some(true),
620            Some(false),
621            Some(false),
622            Some(true),
623            Some(true),
624            Some(false),
625            Some(false),
626            Some(true),
627            Some(true),
628            Some(false),
629            Some(false),
630            Some(true),
631            Some(true),
632            Some(true),
633        ];
634        assert_eq!(
635            decode_bcd(&BITS_MAX_LSB, 0, MAX_BCD_LENGTH - 1),
636            Some(MAX_BCD_VALUE)
637        );
638    }
639
640    #[test]
641    fn ok_decode_bcd_max_msb() {
642        const BITS_MAX_MSB: [Option<bool>; MAX_BCD_LENGTH] = [
643            Some(true),
644            Some(true),
645            Some(true),
646            Some(false),
647            Some(false),
648            Some(true),
649            Some(true),
650            Some(false),
651            Some(false),
652            Some(true),
653            Some(true),
654            Some(false),
655            Some(false),
656            Some(true),
657            Some(true),
658            Some(false),
659            Some(false),
660            Some(true),
661            Some(true),
662            Some(false),
663            Some(false),
664            Some(true),
665            Some(true),
666            Some(false),
667            Some(false),
668            Some(true),
669            Some(true),
670            Some(false),
671            Some(false),
672            Some(true),
673            Some(true),
674            Some(false),
675            Some(false),
676            Some(true),
677            Some(true),
678            Some(false),
679            Some(false),
680            Some(true),
681        ];
682        assert_eq!(
683            decode_bcd(&BITS_MAX_MSB, MAX_BCD_LENGTH - 1, 0),
684            Some(MAX_BCD_VALUE)
685        );
686    }
687
688    #[test]
689    fn ok_decode_parity_regular_even() {
690        assert_eq!(
691            decode_parity(&BIT_BUFFER[0..=4], 0, 3, BIT_BUFFER[4]),
692            Some(false)
693        );
694    }
695
696    #[test]
697    fn bad_decode_parity_none() {
698        assert_eq!(decode_parity(&BIT_BUFFER[7..=9], 0, 1, BIT_BUFFER[2]), None);
699    }
700
701    #[test]
702    fn ok_decode_parity_regular_odd() {
703        assert_eq!(
704            decode_parity(&BIT_BUFFER[0..=3], 0, 2, BIT_BUFFER[3]),
705            Some(true)
706        );
707    }
708
709    #[test]
710    fn ok_decode_parity_backwards() {
711        assert_eq!(
712            decode_parity(&BIT_BUFFER[0..=3], 3, 1, BIT_BUFFER[0]),
713            Some(true)
714        );
715    }
716
717    #[test]
718    fn ok_encode_parity_even() {
719        const BITS: [bool; 8] = [false, true, false, false, true, true, false, true];
720        assert_eq!(encode_parity(&BITS, true), false);
721    }
722
723    #[test]
724    fn ok_encode_parity_odd() {
725        const BITS: [bool; 8] = [false, true, false, false, true, true, false, true];
726        assert_eq!(encode_parity(&BITS, false), true);
727    }
728
729    #[test]
730    fn ok_encode_parity_empty_even() {
731        assert_eq!(encode_parity(&[], true), false);
732    }
733
734    #[test]
735    fn ok_encode_parity_empty_odd() {
736        assert_eq!(encode_parity(&[], false), true);
737    }
738
739    #[test]
740    fn test_encode_bcd_0_lsb_first() {
741        assert_eq!(encode_bcd(0, 8, false), [false; 8]);
742    }
743
744    #[test]
745    fn test_encode_bcd_0_msb_first() {
746        assert_eq!(encode_bcd(0, 8, true), [false; 8]);
747    }
748
749    #[test]
750    fn test_encode_bcd_42_lsb_first() {
751        const BITS: [bool; 7] = [false, true, false, false, false, false, true];
752        assert_eq!(encode_bcd(42, 7, false), BITS);
753    }
754
755    #[test]
756    fn test_encode_bcd_42_msb_first() {
757        const BITS: [bool; 7] = [true, false, false, false, false, true, false];
758        assert_eq!(encode_bcd(42, 7, true), BITS);
759    }
760
761    #[test]
762    fn test_encode_bcd_77_lsb_first() {
763        const BITS: [bool; 8] = [true, true, true, false, true, true, true, false];
764        assert_eq!(encode_bcd(77, 8, false), BITS);
765    }
766
767    #[test]
768    fn test_encode_bcd_77_msb_first() {
769        const BITS: [bool; 8] = [false, true, true, true, false, true, true, true];
770        assert_eq!(encode_bcd(77, 8, true), BITS);
771    }
772
773    #[test]
774    fn test_encode_bcd_99_lsb_first() {
775        const BITS: [bool; 8] = [true, false, false, true, true, false, false, true];
776        assert_eq!(encode_bcd(99, 8, false), BITS);
777    }
778
779    #[test]
780    fn test_encode_bcd_99_msb_first() {
781        const BITS: [bool; 8] = [true, false, false, true, true, false, false, true];
782        assert_eq!(encode_bcd(99, 8, true), BITS);
783    }
784
785    // DCF77 25-4-27 Sun 22:18
786    #[test]
787    fn test_encode_bcd_25_8_lsb_first() {
788        const BITS: [bool; 8] = [true, false, true, false, false, true, false, false];
789        assert_eq!(encode_bcd(25, 8, false), BITS);
790    }
791    #[test]
792    fn test_encode_bcd_4_5_lsb_first() {
793        const BITS: [bool; 5] = [false, false, true, false, false];
794        assert_eq!(encode_bcd(4, 5, false), BITS);
795    }
796    #[test]
797    fn test_encode_bcd_27_6_lsb_first() {
798        const BITS: [bool; 6] = [true, true, true, false, false, true];
799        assert_eq!(encode_bcd(27, 6, false), BITS);
800    }
801    #[test]
802    fn test_encode_bcd_7_3_lsb_first() {
803        const BITS: [bool; 3] = [true, true, true];
804        assert_eq!(encode_bcd(7, 3, false), BITS);
805    }
806    #[test]
807    fn test_encode_bcd_22_6_lsb_first() {
808        const BITS: [bool; 6] = [false, true, false, false, false, true];
809        assert_eq!(encode_bcd(22, 6, false), BITS);
810    }
811    #[test]
812    fn test_encode_bcd_18_7_lsb_first() {
813        const BITS: [bool; 7] = [false, false, false, true, true, false, false];
814        assert_eq!(encode_bcd(18, 7, false), BITS);
815    }
816
817    // MSF 25-4-27 Sun 21:58
818    #[test]
819    fn test_encode_bcd_25_8_msb_first() {
820        const BITS: [bool; 8] = [false, false, true, false, false, true, false, true];
821        assert_eq!(encode_bcd(25, 8, true), BITS);
822    }
823    #[test]
824    fn test_encode_bcd_4_5_msb_first() {
825        const BITS: [bool; 5] = [false, false, true, false, false];
826        assert_eq!(encode_bcd(4, 5, true), BITS);
827    }
828    #[test]
829    fn test_encode_bcd_27_6_msb_first() {
830        const BITS: [bool; 6] = [true, false, false, true, true, true];
831        assert_eq!(encode_bcd(27, 6, true), BITS);
832    }
833    #[test]
834    fn test_encode_bcd_0_3_msb_first() {
835        const BITS: [bool; 3] = [false, false, false];
836        assert_eq!(encode_bcd(0, 3, true), BITS);
837    }
838    #[test]
839    fn test_encode_bcd_21_6_msb_first() {
840        const BITS: [bool; 6] = [true, false, false, false, false, true];
841        assert_eq!(encode_bcd(21, 6, true), BITS);
842    }
843    #[test]
844    fn test_encode_bcd_58_7_msb_first() {
845        const BITS: [bool; 7] = [true, false, true, true, false, false, false];
846        assert_eq!(encode_bcd(58, 7, true), BITS);
847    }
848
849    #[test]
850    fn test_encode_bcd_max_max_lsb_first() {
851        const BITS: [bool; MAX_BCD_LENGTH] = [
852            true, false, false, true, true, false, false, true, true, false, false, true, true,
853            false, false, true, true, false, false, true, true, false, false, true, true, false,
854            false, true, true, false, false, true, true, false, false, true, true, true,
855        ];
856        assert_eq!(encode_bcd(MAX_BCD_VALUE, MAX_BCD_LENGTH as u8, false), BITS);
857    }
858
859    #[test]
860    fn test_encode_bcd_max_max_msb_first() {
861        const BITS: [bool; MAX_BCD_LENGTH] = [
862            true, true, true, false, false, true, true, false, false, true, true, false, false,
863            true, true, false, false, true, true, false, false, true, true, false, false, true,
864            true, false, false, true, true, false, false, true, true, false, false, true,
865        ];
866        assert_eq!(encode_bcd(MAX_BCD_VALUE, MAX_BCD_LENGTH as u8, true), BITS);
867    }
868
869    #[test]
870    fn test_encode_bcd_empty_lsb() {
871        assert_eq!(encode_bcd(0, 0, false), []);
872    }
873
874    #[test]
875    fn test_encode_bcd_empty_msb() {
876        assert_eq!(encode_bcd(0, 0, true), []);
877    }
878
879    #[test]
880    fn test_encode_bcd_too_long_lsb() {
881        assert_eq!(encode_bcd(0, (MAX_BCD_LENGTH + 1) as u8, false), []);
882    }
883
884    #[test]
885    fn test_encode_bcd_too_long_msb() {
886        assert_eq!(encode_bcd(0, (MAX_BCD_LENGTH + 1) as u8, true), []);
887    }
888
889    #[test]
890    fn test_decode_bin_all_0() {
891        const BINARY_BUFFER: [Option<bool>; 32] = [Some(false); 32];
892        assert_eq!(decode_bin(&BINARY_BUFFER, 0, 31), Some(0));
893    }
894
895    #[test]
896    fn test_decode_bin_all_1() {
897        const BINARY_BUFFER: [Option<bool>; 32] = [Some(true); 32];
898        assert_eq!(decode_bin(&BINARY_BUFFER, 0, 31), Some(0xffff_ffff));
899    }
900
901    #[test]
902    fn test_decode_bin_middle() {
903        const BINARY_BUFFER: [Option<bool>; 7] = [
904            Some(true),
905            Some(true),
906            Some(false),
907            Some(false),
908            Some(true),
909            Some(false),
910            Some(true),
911        ];
912        assert_eq!(decode_bin(&BINARY_BUFFER, 0, 6), Some(0x53));
913    }
914
915    #[test]
916    fn test_decode_bin_middle_rev() {
917        const BINARY_BUFFER: [Option<bool>; 7] = [
918            Some(true),
919            Some(true),
920            Some(false),
921            Some(false),
922            Some(true),
923            Some(false),
924            Some(true),
925        ];
926        assert_eq!(decode_bin(&BINARY_BUFFER, 6, 0), Some(0x65));
927    }
928
929    #[test]
930    fn test_decode_bin_invalid_none() {
931        const BINARY_BUFFER: [Option<bool>; 4] = [Some(true), Some(true), None, Some(false)];
932        assert_eq!(decode_bin(&BINARY_BUFFER, 0, 3), None);
933    }
934
935    #[test]
936    fn test_encode_bin_0_lsb_first() {
937        assert_eq!(encode_bin(0, 32, false), [false; 32]);
938    }
939
940    #[test]
941    fn test_encode_bin_0_msb_first() {
942        assert_eq!(encode_bin(0, 32, true), [false; 32]);
943    }
944
945    #[test]
946    fn test_encode_bin_42_lsb_first() {
947        const BITS: [bool; 6] = [false, true, false, true, false, true];
948        assert_eq!(encode_bin(42, 6, false), BITS);
949    }
950
951    #[test]
952    fn test_encode_bin_42_msb_first() {
953        const BITS: [bool; 6] = [true, false, true, false, true, false];
954        assert_eq!(encode_bin(42, 6, true), BITS);
955    }
956
957    #[test]
958    fn test_encode_bin_max_max_lsb() {
959        assert_eq!(encode_bin(0xffff_ffff, 32, false), [true; 32]);
960    }
961
962    #[test]
963    fn test_encode_bin_max_max_msb() {
964        assert_eq!(encode_bin(0xffff_ffff, 32, true), [true; 32]);
965    }
966
967    #[test]
968    fn test_encode_bin_empty_lsb() {
969        assert_eq!(encode_bin(0, 0, false), []);
970    }
971
972    #[test]
973    fn test_encode_bin_empty_msb() {
974        assert_eq!(encode_bin(0, 0, true), []);
975    }
976
977    #[test]
978    fn test_encode_bin_too_long_lsb() {
979        assert_eq!(encode_bin(0, 33, false), []);
980    }
981
982    #[test]
983    fn test_encode_bin_too_long_msb() {
984        assert_eq!(encode_bin(0, 33, true), []);
985    }
986
987    #[test]
988    #[should_panic] // empty ranges are not supported
989    fn test_decode_unary_empty() {
990        assert_eq!(decode_unary(&[], 0, 0), None);
991    }
992
993    #[test]
994    fn test_decode_unary_too_long_lsb() {
995        assert_eq!(decode_unary(&[Some(false); 16], 0, 15), None);
996    }
997
998    #[test]
999    fn test_decode_unary_all_0_lsb() {
1000        const UNARY_BUFFER: [Option<bool>; 15] = [Some(false); 15];
1001        assert_eq!(decode_unary(&UNARY_BUFFER, 0, 14), Some(0));
1002    }
1003
1004    #[test]
1005    fn test_decode_unary_all_1_lsb() {
1006        const UNARY_BUFFER: [Option<bool>; 15] = [Some(true); 15];
1007        assert_eq!(decode_unary(&UNARY_BUFFER, 0, 14), Some(15));
1008    }
1009
1010    #[test]
1011    fn test_decode_unary_middle_lsb() {
1012        const UNARY_BUFFER: [Option<bool>; 4] = [Some(true), Some(true), Some(false), Some(false)];
1013        assert_eq!(decode_unary(&UNARY_BUFFER, 0, 3), Some(2));
1014    }
1015
1016    #[test]
1017    fn test_decode_unary_1_after_0_lsb() {
1018        const UNARY_BUFFER: [Option<bool>; 4] = [Some(false), Some(false), Some(true), Some(false)];
1019        assert_eq!(decode_unary(&UNARY_BUFFER, 0, 3), None);
1020    }
1021
1022    #[test]
1023    fn test_decode_unary_invalid_none_lsb() {
1024        const UNARY_BUFFER: [Option<bool>; 4] = [Some(true), Some(true), None, Some(false)];
1025        assert_eq!(decode_unary(&UNARY_BUFFER, 0, 3), None);
1026    }
1027
1028    #[test]
1029    fn test_decode_unary_too_long_msb() {
1030        assert_eq!(decode_unary(&[Some(false); 16], 15, 0), None);
1031    }
1032
1033    #[test]
1034    fn test_decode_unary_all_0_msb() {
1035        const UNARY_BUFFER: [Option<bool>; 15] = [Some(false); 15];
1036        assert_eq!(decode_unary(&UNARY_BUFFER, 14, 0), Some(0));
1037    }
1038
1039    #[test]
1040    fn test_decode_unary_all_1_msb() {
1041        const UNARY_BUFFER: [Option<bool>; 15] = [Some(true); 15];
1042        assert_eq!(decode_unary(&UNARY_BUFFER, 14, 0), Some(15));
1043    }
1044
1045    #[test]
1046    fn test_decode_unary_middle_msb() {
1047        const UNARY_BUFFER: [Option<bool>; 4] = [Some(false), Some(false), Some(true), Some(true)];
1048        assert_eq!(decode_unary(&UNARY_BUFFER, 3, 0), Some(2));
1049    }
1050
1051    #[test]
1052    fn test_decode_unary_1_after_0_msb() {
1053        const UNARY_BUFFER: [Option<bool>; 4] = [Some(false), Some(false), Some(true), Some(false)];
1054        assert_eq!(decode_unary(&UNARY_BUFFER, 3, 0), None);
1055    }
1056
1057    #[test]
1058    fn test_decode_unary_invalid_none_msb() {
1059        const UNARY_BUFFER: [Option<bool>; 4] = [Some(false), None, Some(true), Some(true)];
1060        assert_eq!(decode_unary(&UNARY_BUFFER, 3, 0), None);
1061    }
1062
1063    #[test]
1064    fn test_encode_unary_0_lsb_first() {
1065        assert_eq!(encode_unary(0, 15, false), [false; 15]);
1066    }
1067
1068    #[test]
1069    fn test_encode_unary_0_msb_first() {
1070        assert_eq!(encode_unary(0, 15, true), [false; 15]);
1071    }
1072
1073    #[test]
1074    fn test_encode_unary_4_lsb_first() {
1075        const BITS: [bool; 6] = [true, true, true, true, false, false];
1076        assert_eq!(encode_unary(4, 6, false), BITS);
1077    }
1078
1079    #[test]
1080    fn test_encode_unary_4_msb_first() {
1081        const BITS: [bool; 6] = [false, false, true, true, true, true];
1082        assert_eq!(encode_unary(4, 6, true), BITS);
1083    }
1084
1085    #[test]
1086    fn test_encode_unary_max_max_lsb() {
1087        assert_eq!(encode_unary(15, 15, false), [true; 15]);
1088    }
1089
1090    #[test]
1091    fn test_encode_unary_max_max_msb() {
1092        assert_eq!(encode_unary(15, 15, true), [true; 15]);
1093    }
1094
1095    #[test]
1096    fn test_encode_unary_empty_lsb() {
1097        assert_eq!(encode_unary(0, 0, false), []);
1098    }
1099
1100    #[test]
1101    fn test_encode_unary_empty_msb() {
1102        assert_eq!(encode_unary(0, 0, true), []);
1103    }
1104
1105    #[test]
1106    fn test_encode_unary_too_long_lsb() {
1107        assert_eq!(encode_unary(0, 16, false), []);
1108    }
1109
1110    #[test]
1111    fn test_encode_unary_too_long_msb() {
1112        assert_eq!(encode_unary(0, 16, true), []);
1113    }
1114}