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
26fn 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
37fn 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}