1use super::{
2 mpv_byte_array, mpv_format_MPV_FORMAT_BYTE_ARRAY, mpv_format_MPV_FORMAT_DOUBLE, mpv_format_MPV_FORMAT_FLAG,
3 mpv_format_MPV_FORMAT_INT64, mpv_format_MPV_FORMAT_NODE_ARRAY, mpv_format_MPV_FORMAT_NODE_MAP,
4 mpv_format_MPV_FORMAT_NONE, mpv_format_MPV_FORMAT_STRING, mpv_node, mpv_node__bindgen_ty_1, mpv_node_list,
5};
6use std::collections::HashMap;
7use std::ffi::{c_char, CStr, CString};
8use std::ptr;
9use std::slice;
10
11#[derive(Debug, Clone, Default)]
12pub enum Node {
13 #[default]
14 None,
15 String(String),
16 Int(i64),
17 Double(f64),
18 Bool(bool),
19 ByteArray(Vec<u8>),
20 Array(Vec<Node>),
21 Map(HashMap<String, Node>),
22}
23
24pub fn from_mpv_node(node: &mut mpv_node) -> Node {
25 match node.format {
26 mpv_format_MPV_FORMAT_STRING => {
27 Node::String(unsafe { CStr::from_ptr(node.u.string) }.to_string_lossy().into_owned())
28 }
29 mpv_format_MPV_FORMAT_INT64 => Node::Int(unsafe { node.u.int64 }),
30 mpv_format_MPV_FORMAT_DOUBLE => Node::Double(unsafe { node.u.double_ }),
31 mpv_format_MPV_FORMAT_FLAG => Node::Bool(unsafe { node.u.flag } != 0),
32 mpv_format_MPV_FORMAT_NODE_ARRAY => {
33 let list = unsafe { &*node.u.list };
34 let values = unsafe { slice::from_raw_parts_mut(list.values, list.num as usize) };
35 Node::Array(values.iter_mut().map(from_mpv_node).collect())
36 }
37 mpv_format_MPV_FORMAT_NODE_MAP => {
38 let list = unsafe { &*node.u.list };
39 let values = unsafe { slice::from_raw_parts_mut(list.values, list.num as usize) };
40 let keys = unsafe { slice::from_raw_parts(list.keys, list.num as usize) };
41 let map = keys
42 .iter()
43 .zip(values.iter_mut())
44 .filter_map(|(&k, v)| {
45 unsafe { k.as_ref() }.map(|key_ptr| {
46 let key = unsafe { CStr::from_ptr(key_ptr) }.to_string_lossy().into_owned();
47 (key, from_mpv_node(v))
48 })
49 })
50 .collect();
51 Node::Map(map)
52 }
53 mpv_format_MPV_FORMAT_BYTE_ARRAY => {
54 let arr: &mpv_byte_array = unsafe { &*node.u.ba };
55 let data = unsafe { slice::from_raw_parts(arr.data as *const u8, arr.size) };
56 Node::ByteArray(data.to_vec())
57 }
58 _ => Node::None,
59 }
60}
61
62pub fn to_mpv_node(node: &Node) -> *mut mpv_node {
63 let mut mpv_node = Box::new(mpv_node {
64 format: 0,
65 u: mpv_node__bindgen_ty_1 { int64: 0 },
66 });
67
68 match node {
69 Node::None => {
70 mpv_node.format = mpv_format_MPV_FORMAT_NONE;
71 }
72 Node::String(s) => {
73 mpv_node.format = mpv_format_MPV_FORMAT_STRING;
74 let cstr = CString::new(s.as_str()).expect("CString::new failed");
75 mpv_node.u.string = cstr.into_raw();
76 }
77 Node::Int(i) => {
78 mpv_node.format = mpv_format_MPV_FORMAT_INT64;
79 mpv_node.u.int64 = *i;
80 }
81 Node::Double(f) => {
82 mpv_node.format = mpv_format_MPV_FORMAT_DOUBLE;
83 mpv_node.u.double_ = *f;
84 }
85 Node::Bool(b) => {
86 mpv_node.format = mpv_format_MPV_FORMAT_FLAG;
87 mpv_node.u.flag = if *b { 1 } else { 0 };
88 }
89 Node::Array(arr) => {
90 mpv_node.format = mpv_format_MPV_FORMAT_NODE_ARRAY;
91 let values: Vec<_> = arr.iter().map(to_mpv_node).collect();
92 let list = Box::new(mpv_node_list {
93 num: values.len() as i32,
94 values: Box::into_raw(values.into_boxed_slice()) as *mut mpv_node,
95 keys: std::ptr::null_mut(),
96 });
97 mpv_node.u.list = Box::into_raw(list);
98 }
99 Node::Map(map) => {
100 mpv_node.format = mpv_format_MPV_FORMAT_NODE_MAP;
101 let (keys, values): (Vec<_>, Vec<_>) = map
102 .iter()
103 .map(|(k, v)| {
104 let ckey = CString::new(k.as_str()).expect("CString::new failed");
105 (ckey.into_raw(), to_mpv_node(v))
106 })
107 .unzip();
108
109 let list = Box::new(mpv_node_list {
110 num: keys.len() as i32,
111 keys: Box::into_raw(keys.into_boxed_slice()) as *mut *mut c_char,
112 values: Box::into_raw(values.into_boxed_slice()) as *mut mpv_node,
113 });
114 mpv_node.u.list = Box::into_raw(list);
115 }
116 Node::ByteArray(vec) => {
117 mpv_node.format = mpv_format_MPV_FORMAT_BYTE_ARRAY;
118 let ba = Box::new(mpv_byte_array {
119 size: vec.len(),
120 data: unsafe { libc::malloc(vec.len()) },
121 });
122 if ba.data.is_null() {
123 panic!("Failed to allocate memory for byte array");
124 }
125 unsafe {
126 ptr::copy_nonoverlapping(vec.as_ptr(), ba.data as *mut u8, vec.len());
127 }
128 mpv_node.u.ba = Box::into_raw(ba);
129 }
130 }
131
132 Box::into_raw(mpv_node)
133}