libdisplay_info/
lib.rs

1#![cfg_attr(docsrs, feature(doc_auto_cfg))]
2
3use std::{
4    ffi::{c_char, CStr},
5    marker::PhantomData,
6};
7
8#[cfg(not(docsrs))]
9mod feature_check {
10    #[cfg(all(feature = "v0_2", feature = "v0_3"))]
11    compile_error!("Either feature \"v0_2\" or \"v0_3\" must be enabled, but not both.");
12}
13
14pub use libdisplay_info_sys as ffi;
15
16pub mod cta;
17pub mod cvt;
18pub mod displayid;
19#[cfg(feature = "v0_3")]
20pub mod displayid2;
21pub mod dmt;
22pub mod edid;
23pub mod gtf;
24pub mod info;
25
26/// Get the [`String`] from an owned ffi ptr
27///
28/// This will automatically free the ptr
29fn string_from_ffi_ptr(ptr: *const c_char) -> Option<String> {
30    if ptr.is_null() {
31        None
32    } else {
33        Some(unsafe { CStr::from_ptr(ptr).to_string_lossy().into_owned() })
34    }
35}
36
37/// Get the [`String`] from an owned ffi ptr
38///
39/// This will automatically free the ptr
40///
41/// `None` is returned for NULL ptr
42fn string_from_owned_ffi_ptr(ptr: *mut c_char) -> Option<String> {
43    let res = string_from_ffi_ptr(ptr);
44    if res.is_some() {
45        unsafe {
46            libc::free(ptr as *mut _);
47        }
48    }
49    res
50}
51
52struct FFIIter<'a, T, F> {
53    ptr: *const *const F,
54    t: PhantomData<T>,
55    phantom: PhantomData<&'a ()>,
56}
57
58impl<T, F> FFIIter<'_, T, F> {
59    fn new(ptr: *const *const F) -> Self {
60        Self {
61            ptr,
62            t: PhantomData,
63            phantom: PhantomData,
64        }
65    }
66}
67
68impl<T, F> Iterator for FFIIter<'_, T, F>
69where
70    T: From<F>,
71    F: Copy,
72{
73    type Item = T;
74
75    fn next(&mut self) -> Option<Self::Item> {
76        if self.ptr.is_null() || unsafe { *self.ptr }.is_null() {
77            None
78        } else {
79            let item = T::from(unsafe { *(*self.ptr) });
80            self.ptr = self.ptr.wrapping_add(1);
81            Some(item)
82        }
83    }
84}