xref: /webrtc/rtcp/src/util.rs (revision 8b68b472)
1 use crate::error::{Error, Result};
2 
3 use bytes::BufMut;
4 
5 // returns the padding required to make the length a multiple of 4
6 pub(crate) fn get_padding_size(len: usize) -> usize {
7     if len % 4 == 0 {
8         0
9     } else {
10         4 - (len % 4)
11     }
12 }
13 
14 pub(crate) fn put_padding(mut buf: &mut [u8], len: usize) {
15     let padding_size = get_padding_size(len);
16     for i in 0..padding_size {
17         if i == padding_size - 1 {
18             buf.put_u8(padding_size as u8);
19         } else {
20             buf.put_u8(0);
21         }
22     }
23 }
24 
25 // set_nbits_of_uint16 will truncate the value to size, left-shift to start_index position and set
26 pub(crate) fn set_nbits_of_uint16(
27     src: u16,
28     size: u16,
29     start_index: u16,
30     mut val: u16,
31 ) -> Result<u16> {
32     if start_index + size > 16 {
33         return Err(Error::InvalidSizeOrStartIndex);
34     }
35 
36     // truncate val to size bits
37     val &= (1 << size) - 1;
38 
39     Ok(src | (val << (16 - size - start_index)))
40 }
41 
42 // appendBit32 will left-shift and append n bits of val
43 pub(crate) fn append_nbits_to_uint32(src: u32, n: u32, val: u32) -> u32 {
44     (src << n) | (val & (0xFFFFFFFF >> (32 - n)))
45 }
46 
47 // getNBit get n bits from 1 byte, begin with a position
48 pub(crate) fn get_nbits_from_byte(b: u8, begin: u16, n: u16) -> u16 {
49     let end_shift = 8 - (begin + n);
50     let mask = (0xFF >> begin) & (0xFF << end_shift) as u8;
51     (b & mask) as u16 >> end_shift
52 }
53 
54 // get24BitFromBytes get 24bits from `[3]byte` slice
55 pub(crate) fn get_24bits_from_bytes(b: &[u8]) -> u32 {
56     ((b[0] as u32) << 16) + ((b[1] as u32) << 8) + (b[2] as u32)
57 }
58 
59 #[cfg(test)]
60 mod test {
61     use super::*;
62 
63     #[test]
64     fn test_get_padding() -> Result<()> {
65         let tests = vec![(0, 0), (1, 3), (2, 2), (3, 1), (4, 0), (100, 0), (500, 0)];
66 
67         for (n, p) in tests {
68             assert_eq!(
69                 get_padding_size(n),
70                 p,
71                 "Test case returned wrong value for input {}",
72                 n
73             );
74         }
75 
76         Ok(())
77     }
78 
79     #[test]
80     fn test_set_nbits_of_uint16() -> Result<()> {
81         let tests = vec![
82             ("setOneBit", 0, 1, 8, 1, 128, None),
83             ("setStatusVectorBit", 0, 1, 0, 1, 32768, None),
84             ("setStatusVectorSecondBit", 32768, 1, 1, 1, 49152, None),
85             (
86                 "setStatusVectorInnerBitsAndCutValue",
87                 49152,
88                 2,
89                 6,
90                 11111,
91                 49920,
92                 None,
93             ),
94             ("setRunLengthSecondTwoBit", 32768, 2, 1, 1, 40960, None),
95             (
96                 "setOneBitOutOfBounds",
97                 32768,
98                 2,
99                 15,
100                 1,
101                 0,
102                 Some("invalid size or startIndex"),
103             ),
104         ];
105 
106         for (name, source, size, index, value, result, err) in tests {
107             let res = set_nbits_of_uint16(source, size, index, value);
108             if err.is_some() {
109                 assert!(res.is_err(), "setNBitsOfUint16 {} : should be error", name);
110             } else if let Ok(got) = res {
111                 assert_eq!(got, result, "setNBitsOfUint16 {}", name);
112             } else {
113                 panic!("setNBitsOfUint16 {} :unexpected error result", name);
114             }
115         }
116 
117         Ok(())
118     }
119 }
120