xref: /webrtc/rtcp/src/util.rs (revision 5d8fe953)
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
get_padding_size(len: usize) -> usize6 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 
put_padding(mut buf: &mut [u8], len: usize)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
set_nbits_of_uint16( src: u16, size: u16, start_index: u16, mut val: u16, ) -> Result<u16>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
append_nbits_to_uint32(src: u32, n: u32, val: u32) -> u3243 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
get_nbits_from_byte(b: u8, begin: u16, n: u16) -> u1648 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
get_24bits_from_bytes(b: &[u8]) -> u3255 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]
test_get_padding() -> Result<()>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 {n}"
72             );
73         }
74 
75         Ok(())
76     }
77 
78     #[test]
test_set_nbits_of_uint16() -> Result<()>79     fn test_set_nbits_of_uint16() -> Result<()> {
80         let tests = vec![
81             ("setOneBit", 0, 1, 8, 1, 128, None),
82             ("setStatusVectorBit", 0, 1, 0, 1, 32768, None),
83             ("setStatusVectorSecondBit", 32768, 1, 1, 1, 49152, None),
84             (
85                 "setStatusVectorInnerBitsAndCutValue",
86                 49152,
87                 2,
88                 6,
89                 11111,
90                 49920,
91                 None,
92             ),
93             ("setRunLengthSecondTwoBit", 32768, 2, 1, 1, 40960, None),
94             (
95                 "setOneBitOutOfBounds",
96                 32768,
97                 2,
98                 15,
99                 1,
100                 0,
101                 Some("invalid size or startIndex"),
102             ),
103         ];
104 
105         for (name, source, size, index, value, result, err) in tests {
106             let res = set_nbits_of_uint16(source, size, index, value);
107             if err.is_some() {
108                 assert!(res.is_err(), "setNBitsOfUint16 {name} : should be error");
109             } else if let Ok(got) = res {
110                 assert_eq!(got, result, "setNBitsOfUint16 {name}");
111             } else {
112                 panic!("setNBitsOfUint16 {name} :unexpected error result");
113             }
114         }
115 
116         Ok(())
117     }
118 }
119