ddcutil/
lib.rs

1#![doc(html_root_url = "http://arcnmx.github.io/ddcutil-rs/")]
2pub extern crate ddcutil_sys as sys;
3extern crate libc;
4#[macro_use]
5extern crate bitflags;
6
7use std::{result, str};
8
9mod status;
10pub use status::{Status, Error};
11pub type Result<T> = result::Result<T, Error>;
12
13mod display;
14pub use display::*;
15
16mod features;
17pub use features::*;
18
19pub type Version = sys::DDCA_Ddcutil_Version_Spec;
20
21unsafe fn c_str<'a>(ptr: *const libc::c_char) -> result::Result<&'a str, str::Utf8Error> {
22    use std::ffi::CStr;
23
24    str::from_utf8(CStr::from_ptr(ptr).to_bytes())
25}
26
27pub fn version() -> Version {
28    unsafe {
29        sys::ddca_ddcutil_version()
30    }
31}
32
33pub fn version_string() -> &'static str {
34    unsafe {
35        c_str(sys::ddca_ddcutil_version_string())
36            .expect("ddcutil returned invalid version string")
37    }
38}
39
40pub fn verification_enabled() -> bool {
41    unsafe {
42        sys::ddca_is_verify_enabled()
43    }
44}
45
46pub fn set_verification(onoff: bool) {
47    unsafe {
48        sys::ddca_enable_verify(onoff)
49    }
50}
51
52#[repr(u8)]
53#[derive(Debug, Copy, Clone, PartialEq, Eq, PartialOrd, Ord, Hash)]
54pub enum OutputLevel {
55    Terse = sys::DDCA_OL_TERSE as _,
56    Normal = sys::DDCA_OL_NORMAL as _,
57    Verbose = sys::DDCA_OL_VERBOSE as _,
58}
59
60impl Default for OutputLevel {
61    fn default() -> Self {
62        OutputLevel::Normal
63    }
64}
65
66impl OutputLevel {
67    pub fn from_raw(raw: sys::DDCA_Output_Level) -> result::Result<Self, ()> {
68        match raw {
69            sys::DDCA_OL_TERSE => Ok(OutputLevel::Terse),
70            sys::DDCA_OL_NORMAL => Ok(OutputLevel::Normal),
71            sys::DDCA_OL_VERBOSE => Ok(OutputLevel::Verbose),
72            _ => Err(()),
73        }
74    }
75
76    pub fn to_raw(&self) -> sys::DDCA_Output_Level {
77        *self as _
78    }
79}
80
81pub fn output_level() -> OutputLevel {
82    unsafe {
83        OutputLevel::from_raw(sys::ddca_get_output_level())
84            .expect("invalid output level")
85    }
86}
87
88pub fn set_output_level(value: OutputLevel) {
89    unsafe {
90        sys::ddca_set_output_level(value.to_raw())
91    }
92}
93
94#[repr(u8)]
95#[derive(Debug, Copy, Clone, PartialEq, Eq, PartialOrd, Ord, Hash)]
96pub enum RetryType {
97    WriteOnly = sys::DDCA_WRITE_ONLY_TRIES as _,
98    WriteRead = sys::DDCA_WRITE_READ_TRIES as _,
99    MultiPart = sys::DDCA_MULTI_PART_TRIES as _,
100}
101
102impl RetryType {
103    pub fn to_raw(&self) -> sys::DDCA_Retry_Type {
104        *self as _
105    }
106}
107
108pub fn max_retries() -> usize {
109    unsafe {
110        sys::ddca_max_max_tries() as _
111    }
112}
113
114pub fn get_retries(ty: RetryType) -> usize {
115    unsafe {
116        sys::ddca_get_max_tries(ty.to_raw()) as _
117    }
118}
119
120pub fn set_retries(ty: RetryType, value: usize) -> Result<()> {
121    unsafe {
122        Error::from_status(sys::ddca_set_max_tries(ty.to_raw(), value as _)).map(drop)
123    }
124}
125
126#[test]
127fn test_api() {
128    let _ = version();
129    let _ = version_string();
130    let _ = output_level();
131    let _ = verification_enabled();
132    let _ = max_retries();
133    for ty in vec![RetryType::WriteOnly, RetryType::WriteRead, RetryType::MultiPart] {
134        let _ = get_retries(ty);
135    }
136}
137
138#[test]
139fn test_output_level() {
140    for level in vec![OutputLevel::Terse, OutputLevel::Normal, OutputLevel::Verbose] {
141        set_output_level(level);
142    }
143}
144
145#[test]
146fn test_retries() {
147    let max = max_retries();
148    for ty in vec![RetryType::WriteOnly, RetryType::WriteRead, RetryType::MultiPart] {
149        for retry in 1..(max + 1) {
150            assert!(set_retries(ty, retry).is_ok());
151        }
152        assert!(set_retries(ty, max + 1).is_err());
153    }
154}