gpiod_core/
utils.rs

1use crate::{Error, Result, Time};
2use std::{io, mem::size_of_val, str, time};
3
4#[inline(always)]
5pub fn time_from_nanos(nanos: u64) -> Time {
6    time::Duration::from_nanos(nanos)
7}
8
9#[inline(always)]
10pub fn is_set<T>(flags: T, flag: T) -> bool
11where
12    T: core::ops::BitAnd<Output = T> + Eq + Copy,
13{
14    flags & flag == flag
15}
16
17#[inline(always)]
18pub fn invalid_input(msg: &'static str) -> Error {
19    Error::new(io::ErrorKind::InvalidInput, msg)
20}
21
22#[inline(always)]
23pub fn invalid_data(msg: &'static str) -> Error {
24    Error::new(io::ErrorKind::InvalidData, msg)
25}
26
27#[inline(always)]
28pub fn check_size<T: ?Sized>(len: usize, val: &T) -> Result<()> {
29    if len == size_of_val(val) {
30        Ok(())
31    } else {
32        Err(invalid_data("Unexpected size"))
33    }
34}
35
36#[inline(always)]
37pub fn check_len<V, T: ?Sized>(slice: &[V], val: &T) -> Result<()> {
38    if slice.len() <= size_of_val(val) {
39        Ok(())
40    } else {
41        Err(invalid_input("Too many values"))
42    }
43}
44
45#[inline(always)]
46pub fn check_len_str<T: ?Sized>(slice: &str, val: &T) -> Result<()> {
47    if slice.as_bytes().len() /* \0 */ < size_of_val(val) {
48        Ok(())
49    } else {
50        Err(invalid_input("String too long"))
51    }
52}
53
54#[inline(always)]
55pub fn safe_set_str<const N: usize>(dst: &mut [u8; N], src: &str) -> Result<()> {
56    check_len_str(src, dst)?;
57
58    let src = src.as_bytes();
59    dst[..src.len()].copy_from_slice(src);
60    dst[src.len()] = 0;
61
62    Ok(())
63}
64
65#[inline(always)]
66pub fn safe_get_str(src: &[u8]) -> Result<&str> {
67    Ok(str::from_utf8(src)
68        .map_err(|_| invalid_data("Invalid UTF-8"))?
69        .trim_end_matches('\0'))
70}
71
72/// This definition from libc
73#[inline(always)]
74pub fn major(dev: u64) -> u64 {
75    let mut major = 0;
76    major |= (dev & 0x00000000000fff00) >> 8;
77    major |= (dev & 0xfffff00000000000) >> 32;
78    major
79}
80
81/// This definition from libc
82#[inline(always)]
83pub fn minor(dev: u64) -> u64 {
84    let mut minor = 0;
85    minor |= dev & 0x00000000000000ff;
86    minor |= (dev & 0x00000ffffff00000) >> 12;
87    minor
88}
89
90/// Set non-block flag to fd
91pub fn set_nonblock(fd: std::os::unix::io::RawFd) -> Result<()> {
92    use nix::fcntl::{fcntl, FcntlArg, OFlag};
93
94    let mut flags = OFlag::from_bits_truncate(fcntl(fd, FcntlArg::F_GETFL)?);
95
96    flags.insert(OFlag::O_NONBLOCK);
97
98    fcntl(fd, FcntlArg::F_SETFL(flags))?;
99
100    Ok(())
101}