use std::{
ffi::{c_char, CString},
ops::{Bound, RangeBounds},
};
pub fn convert_bounds(range: impl RangeBounds<u64>) -> (u64, u64) {
let start = match range.start_bound() {
Bound::Included(&start) => start,
Bound::Excluded(&start) => start + 1,
Bound::Unbounded => 0,
};
let end = match range.end_bound() {
Bound::Included(&end) => end,
Bound::Excluded(&end) => end - 1,
Bound::Unbounded => u64::MAX,
};
(start, end)
}
pub fn to_null_terminated_c_array(strings: &[CString]) -> Vec<*const c_char> {
let mut ptrs: Vec<*const c_char> = strings.iter().map(|s| s.as_ptr()).collect();
ptrs.push(std::ptr::null());
ptrs
}
pub fn format_mode(mode: u32) -> String {
let file_type = match mode & 0o170000 {
0o040000 => 'd', 0o120000 => 'l', 0o010000 => 'p', 0o140000 => 's', 0o060000 => 'b', 0o020000 => 'c', _ => '-', };
let user = format_triplet((mode >> 6) & 0o7);
let group = format_triplet((mode >> 3) & 0o7);
let other = format_triplet(mode & 0o7);
format!("{}{}{}{}", file_type, user, group, other)
}
fn format_triplet(mode: u32) -> String {
let r = if mode & 0o4 != 0 { 'r' } else { '-' };
let w = if mode & 0o2 != 0 { 'w' } else { '-' };
let x = if mode & 0o1 != 0 { 'x' } else { '-' };
format!("{}{}{}", r, w, x)
}
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn test_format_mode() {
assert_eq!(format_mode(0o755), "-rwxr-xr-x");
assert_eq!(format_mode(0o644), "-rw-r--r--");
assert_eq!(format_mode(0o40755), "drwxr-xr-x");
assert_eq!(format_mode(0o100644), "-rw-r--r--");
assert_eq!(format_mode(0o120777), "lrwxrwxrwx");
assert_eq!(format_mode(0o010644), "prw-r--r--");
}
}