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}