Coverage Report

Created: 2026-08-14 08:14

next uncovered line (L), next uncovered region (R), next uncovered branch (B)
/rust/registry/src/index.crates.io-1949cf8c6b5b557f/fst-0.4.7/src/bytes.rs
Line
Count
Source
1
use std::convert::TryInto;
2
use std::io;
3
4
/// Read a u32 in little endian format from the beginning of the given slice.
5
/// This panics if the slice has length less than 4.
6
#[inline]
7
0
pub fn read_u32_le(slice: &[u8]) -> u32 {
8
0
    u32::from_le_bytes(slice[..4].try_into().unwrap())
9
0
}
10
11
/// Read a u64 in little endian format from the beginning of the given slice.
12
/// This panics if the slice has length less than 8.
13
#[inline]
14
0
pub fn read_u64_le(slice: &[u8]) -> u64 {
15
0
    u64::from_le_bytes(slice[..8].try_into().unwrap())
16
0
}
17
18
/// Write a u32 in little endian format to the beginning of the given slice.
19
/// This panics if the slice has length less than 4.
20
#[inline]
21
0
pub fn write_u32_le(n: u32, slice: &mut [u8]) {
22
0
    assert!(slice.len() >= 4);
23
0
    let bytes = n.to_le_bytes();
24
0
    slice[0] = bytes[0];
25
0
    slice[1] = bytes[1];
26
0
    slice[2] = bytes[2];
27
0
    slice[3] = bytes[3];
28
0
}
29
30
/// Like write_u32_le, but to an io::Write implementation. If every byte could
31
/// not be writen, then this returns an error.
32
#[inline]
33
0
pub fn io_write_u32_le<W: io::Write>(n: u32, mut wtr: W) -> io::Result<()> {
34
0
    let mut buf = [0; 4];
35
0
    write_u32_le(n, &mut buf);
36
0
    wtr.write_all(&buf)
37
0
}
38
39
/// Write a u64 in little endian format to the beginning of the given slice.
40
/// This panics if the slice has length less than 8.
41
#[inline]
42
0
pub fn write_u64_le(n: u64, slice: &mut [u8]) {
43
0
    assert!(slice.len() >= 8);
44
0
    let bytes = n.to_le_bytes();
45
0
    slice[0] = bytes[0];
46
0
    slice[1] = bytes[1];
47
0
    slice[2] = bytes[2];
48
0
    slice[3] = bytes[3];
49
0
    slice[4] = bytes[4];
50
0
    slice[5] = bytes[5];
51
0
    slice[6] = bytes[6];
52
0
    slice[7] = bytes[7];
53
0
}
54
55
/// Like write_u64_le, but to an io::Write implementation. If every byte could
56
/// not be writen, then this returns an error.
57
#[inline]
58
0
pub fn io_write_u64_le<W: io::Write>(n: u64, mut wtr: W) -> io::Result<()> {
59
0
    let mut buf = [0; 8];
60
0
    write_u64_le(n, &mut buf);
61
0
    wtr.write_all(&buf)
62
0
}
63
64
/// pack_uint packs the given integer in the smallest number of bytes possible,
65
/// and writes it to the given writer. The number of bytes written is returned
66
/// on success.
67
#[inline]
68
0
pub fn pack_uint<W: io::Write>(wtr: W, n: u64) -> io::Result<u8> {
69
0
    let nbytes = pack_size(n);
70
0
    pack_uint_in(wtr, n, nbytes).map(|_| nbytes)
71
0
}
72
73
/// pack_uint_in is like pack_uint, but always uses the number of bytes given
74
/// to pack the number given.
75
///
76
/// `nbytes` must be >= pack_size(n) and <= 8, where `pack_size(n)` is the
77
/// smallest number of bytes that can store the integer given.
78
#[inline]
79
0
pub fn pack_uint_in<W: io::Write>(
80
0
    mut wtr: W,
81
0
    mut n: u64,
82
0
    nbytes: u8,
83
0
) -> io::Result<()> {
84
0
    assert!(1 <= nbytes && nbytes <= 8);
85
0
    let mut buf = [0u8; 8];
86
0
    for i in 0..nbytes {
87
0
        buf[i as usize] = n as u8;
88
0
        n = n >> 8;
89
0
    }
90
0
    wtr.write_all(&buf[..nbytes as usize])?;
91
0
    Ok(())
92
0
}
93
94
/// unpack_uint is the dual of pack_uint. It unpacks the integer at the current
95
/// position in `slice` after reading `nbytes` bytes.
96
///
97
/// `nbytes` must be >= 1 and <= 8.
98
#[inline]
99
0
pub fn unpack_uint(slice: &[u8], nbytes: u8) -> u64 {
100
0
    assert!(1 <= nbytes && nbytes <= 8);
101
102
0
    let mut n = 0;
103
0
    for (i, &b) in slice[..nbytes as usize].iter().enumerate() {
104
0
        n = n | ((b as u64) << (8 * i));
105
0
    }
106
0
    n
107
0
}
108
109
/// pack_size returns the smallest number of bytes that can encode `n`.
110
#[inline]
111
0
pub fn pack_size(n: u64) -> u8 {
112
0
    if n < 1 << 8 {
113
0
        1
114
0
    } else if n < 1 << 16 {
115
0
        2
116
0
    } else if n < 1 << 24 {
117
0
        3
118
0
    } else if n < 1 << 32 {
119
0
        4
120
0
    } else if n < 1 << 40 {
121
0
        5
122
0
    } else if n < 1 << 48 {
123
0
        6
124
0
    } else if n < 1 << 56 {
125
0
        7
126
    } else {
127
0
        8
128
    }
129
0
}
130
131
#[cfg(test)]
132
mod tests {
133
    use super::*;
134
    use quickcheck::{QuickCheck, StdGen};
135
    use std::io;
136
137
    #[test]
138
    fn prop_pack_in_out() {
139
        fn p(num: u64) -> bool {
140
            let mut buf = io::Cursor::new(vec![]);
141
            let size = pack_uint(&mut buf, num).unwrap();
142
            buf.set_position(0);
143
            num == unpack_uint(buf.get_ref(), size)
144
        }
145
        QuickCheck::new()
146
            .gen(StdGen::new(::rand::thread_rng(), 257)) // pick byte boundary
147
            .quickcheck(p as fn(u64) -> bool);
148
    }
149
}