1
  2
  3
  4
  5
  6
  7
  8
  9
 10
 11
 12
 13
 14
 15
 16
 17
 18
 19
 20
 21
 22
 23
 24
 25
 26
 27
 28
 29
 30
 31
 32
 33
 34
 35
 36
 37
 38
 39
 40
 41
 42
 43
 44
 45
 46
 47
 48
 49
 50
 51
 52
 53
 54
 55
 56
 57
 58
 59
 60
 61
 62
 63
 64
 65
 66
 67
 68
 69
 70
 71
 72
 73
 74
 75
 76
 77
 78
 79
 80
 81
 82
 83
 84
 85
 86
 87
 88
 89
 90
 91
 92
 93
 94
 95
 96
 97
 98
 99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
pub const U16_MAX: u32 = u16::max_value() as u32;
pub const U32_MAX: u64 = u32::max_value() as u64;

/// returns the u16 high bits from a u32
pub fn u32_high_bits(i: u32) -> u16 {
    (i >> 16) as u16
}

/// returns the u16 low bits from a u32 by doing a lossy cast
pub fn u32_low_bits(i: u32) -> u16 {
    (i as u16)
}

/// splits the high and low bits of u32 into a tuple of u16, for destructuring convenience
pub fn u32_split_bits(i: u32) -> (u16, u16) {
    (u32_high_bits(i), u32_low_bits(i))
}

/// merges 2x u16 into a single u32
pub fn u32_merge_bits(high: u16, low: u16) -> u32 {
    (u32::from(high) << 16) | u32::from(low)
}

pub fn u64_high_bits(i: u64) -> u32 {
    (i >> 32) as u32
}

pub fn u64_low_bits(i: u64) -> u32 {
    (i as u32)
}

pub fn u64_split_bits(i: u64) -> (u32, u32) {
    (u64_high_bits(i), u64_low_bits(i))
}

pub fn u64_merge_bits(high: u32, low: u32) -> u64 {
    (u64::from(high) << 32) | u64::from(low)
}

#[cfg(test)]
pub mod tests {

    #[test]
    /// tests that we can extract the high bits from a u32 into the correct u16
    fn u32_high_bits_test() {
        assert_eq!(
            0b1010101010101010,
            super::u32_high_bits(0b1010101010101010_0101010101010101),
        );
    }

    #[test]
    /// tests that we can extract the high bits from a u32 into the correct u16
    fn u32_low_bits_test() {
        assert_eq!(
            0b0101010101010101,
            super::u32_low_bits(0b1010101010101010_0101010101010101),
        );
    }

    #[test]
    /// tests that we can split a u32 into a tuple of high/low bits
    fn u32_split_bits_test() {
        assert_eq!(
            (0b1010101010101010, 0b0101010101010101),
            super::u32_split_bits(0b1010101010101010_0101010101010101),
        );
    }

    #[test]
    /// tests that we can merge a u16 tuple into a u32
    fn u32_merge_bits_test() {
        assert_eq!(
            0b1010101010101010_0101010101010101,
            super::u32_merge_bits(0b1010101010101010, 0b0101010101010101),
        );
    }

    #[test]
    /// tests that we can extract the high bits from a u64 into the correct u32
    fn u64_high_bits_test() {
        assert_eq!(
            0b10101010_10101010_10101010_10101010,
            super::u64_high_bits(
                0b10101010_10101010_10101010_10101010_01010101_01010101_01010101_01010101
            ),
        );
    }

    #[test]
    /// tests that we can extract the high bits from a u64 into the correct u32
    fn u64_low_bits_test() {
        assert_eq!(
            0b01010101_01010101_01010101_01010101,
            super::u64_low_bits(
                0b10101010_10101010_10101010_10101010_01010101_01010101_01010101_01010101
            ),
        );
    }

    #[test]
    /// tests that we can split a u64 into a tuple of high/low bits
    fn u64_split_bits_test() {
        assert_eq!(
            (
                0b10101010_10101010_10101010_10101010,
                0b01010101_01010101_01010101_01010101
            ),
            super::u64_split_bits(
                0b10101010_10101010_10101010_10101010_01010101_01010101_01010101_01010101
            ),
        );
    }

    #[test]
    /// tests that we can merge a u32 tuple into a u64
    fn u64_merge_bits_test() {
        assert_eq!(
            0b10101010_10101010_10101010_10101010_01010101_01010101_01010101_01010101,
            super::u64_merge_bits(
                0b10101010_10101010_10101010_10101010,
                0b01010101_01010101_01010101_01010101
            ),
        );
    }

}