1use super::ffi::mpv_free;
2use super::Result;
3
4use std::ffi::{c_char, c_int, c_void, CStr, CString};
5
6pub trait Format: Sized + Default {
7 const MPV_FORMAT: i32;
8 fn from_ptr(ptr: *const c_void) -> Result<Self>;
9 fn to_mpv<F: Fn(*const c_void) -> Result<()>>(self, fun: F) -> Result<()>;
10 fn from_mpv<F: Fn(*mut c_void) -> Result<()>>(fun: F) -> Result<Self>;
11}
12
13impl Format for String {
14 const MPV_FORMAT: i32 = 1;
15
16 fn from_ptr(ptr: *const c_void) -> Result<Self> {
17 let ptr = ptr as *const *const c_char;
18 Ok(unsafe { CStr::from_ptr(*ptr) }.to_str()?.to_string())
19 }
20
21 fn to_mpv<F: Fn(*const c_void) -> Result<()>>(self, fun: F) -> Result<()> {
22 let str = CString::new::<String>(self.into())?;
23 fun(&str.as_ptr() as *const *const c_char as *const c_void)
24 }
25
26 fn from_mpv<F: Fn(*mut c_void) -> Result<()>>(fun: F) -> Result<Self> {
27 let mut ptr: *mut c_char = std::ptr::null_mut();
28 fun(&mut ptr as *mut _ as *mut c_void).and_then(|()| unsafe {
29 let str = CStr::from_ptr(ptr);
30 let str = str.to_str().map(|s| s.to_owned());
31 mpv_free(ptr as *mut c_void);
32 Ok(str?)
33 })
34 }
35}
36
37impl Format for bool {
38 const MPV_FORMAT: i32 = 3;
39
40 fn from_ptr(ptr: *const c_void) -> Result<Self> {
41 Ok(unsafe { *(ptr as *const c_int) != 0 })
42 }
43
44 fn to_mpv<F: Fn(*const c_void) -> Result<()>>(self, fun: F) -> Result<()> {
45 let data = self as c_int;
46 fun(&data as *const _ as *const c_void)
47 }
48
49 fn from_mpv<F: Fn(*mut c_void) -> Result<()>>(fun: F) -> Result<Self> {
50 let mut data = Self::default() as c_int;
51 fun(&mut data as *mut _ as *mut c_void).map(|()| data != 0)
52 }
53}
54
55impl Format for i64 {
56 const MPV_FORMAT: i32 = 4;
57
58 fn from_ptr(ptr: *const c_void) -> Result<Self> {
59 Ok(unsafe { *(ptr as *const Self) })
60 }
61
62 fn to_mpv<F: Fn(*const c_void) -> Result<()>>(self, fun: F) -> Result<()> {
63 fun(&self as *const _ as *const c_void)
64 }
65
66 fn from_mpv<F: Fn(*mut c_void) -> Result<()>>(fun: F) -> Result<Self> {
67 let mut data = Self::default();
68 fun(&mut data as *mut _ as *mut c_void).map(|()| data)
69 }
70}
71
72impl Format for f64 {
73 const MPV_FORMAT: i32 = 5;
74
75 fn from_ptr(ptr: *const c_void) -> Result<Self> {
76 Ok(unsafe { *(ptr as *const Self) })
77 }
78
79 fn to_mpv<F: Fn(*const c_void) -> Result<()>>(self, fun: F) -> Result<()> {
80 fun(&self as *const _ as *const c_void)
81 }
82
83 fn from_mpv<F: Fn(*mut c_void) -> Result<()>>(fun: F) -> Result<Self> {
84 let mut data = Self::default();
85 fun(&mut data as *mut _ as *mut c_void).map(|()| data)
86 }
87}