libmpv_client/types/
node_map.rs1use std::collections::HashMap;
2use std::ffi::{CStr, CString,c_char, c_int, c_void};
3use std::marker::PhantomData;
4use std::mem::MaybeUninit;
5use std::ptr::null_mut;
6use libmpv_client_sys::{mpv_node, mpv_node_list};
7use crate::*;
8use crate::node::MpvNode;
9use crate::types::traits::{MpvFormat, MpvRecv, MpvRecvInternal, MpvRepr, MpvSend, MpvSendInternal, ToMpvRepr};
10
11pub type NodeMap = HashMap<String, Node>;
13
14#[derive(Debug)]
15pub(crate) struct MpvNodeMap<'a> {
16 _original: PhantomData<&'a NodeMap>,
17
18 _owned_reprs: Vec<MpvNode<'a>>,
19 _flat_reprs: Vec<mpv_node>,
20
21 _owned_keys: Vec<CString>,
22 _flat_keys: Vec<*const c_char>,
23
24 node_list: Box<mpv_node_list>,
25}
26
27impl MpvRepr for MpvNodeMap<'_> {
28 type Repr = mpv_node_list;
29
30 fn ptr(&self) -> *const Self::Repr {
31 &raw const *self.node_list
32 }
33}
34
35impl MpvFormat for NodeMap {
36 const MPV_FORMAT: Format = Format::NODE_MAP;
37}
38
39impl From<NodeMap> for Node {
40 fn from(value: NodeMap) -> Self {
41 Node::Map(value)
42 }
43}
44
45impl From<&NodeMap> for Node {
46 fn from(value: &NodeMap) -> Self {
47 Node::Map(value.clone())
48 }
49}
50
51impl MpvRecv for NodeMap {}
52impl MpvRecvInternal for NodeMap {
53 unsafe fn from_ptr(ptr: *const c_void) -> Result<Self> {
54 check_null!(ptr);
55
56 let node_list = unsafe { *(ptr as *const mpv_node_list) };
57
58 check_null!(node_list.values);
59 check_null!(node_list.keys);
60
61 let mut values = Vec::with_capacity(node_list.num as usize);
62 let mut keys = Vec::with_capacity(node_list.num as usize);
63
64 let node_values = unsafe { std::slice::from_raw_parts(node_list.values, node_list.num as usize) };
65 for node_value in node_values {
66 values.push(unsafe { Node::from_node_ptr(node_value)? });
67 }
68
69 let node_keys = unsafe { std::slice::from_raw_parts(node_list.keys, node_list.num as usize) };
70 for node_key in node_keys {
71 keys.push(unsafe { CStr::from_ptr(*node_key) }.to_str()?.to_string());
72 }
73
74 let map = keys.into_iter().zip(values).collect();
75
76 Ok(map)
77 }
78
79 unsafe fn from_mpv<F: Fn(*mut c_void) -> Result<i32>>(fun: F) -> Result<Self> {
80 let mut node_list: MaybeUninit<mpv_node_list> = MaybeUninit::uninit();
81
82 fun(node_list.as_mut_ptr() as *mut c_void).map(|_| {
83 unsafe { Self::from_ptr(node_list.as_ptr() as *const c_void) }
84 })?
85 }
86}
87
88impl MpvSend for NodeMap {}
89impl MpvSendInternal for NodeMap {
90 fn to_mpv<F: Fn(*mut c_void) -> Result<i32>>(&self, fun: F) -> Result<i32> {
91 let repr = self.to_mpv_repr();
92
93 fun(repr.ptr() as *mut c_void)
94 }
95}
96
97impl ToMpvRepr for NodeMap {
98 type ReprWrap<'a> = MpvNodeMap<'a>;
99
100 fn to_mpv_repr(&self) -> Self::ReprWrap<'_> {
101 let mut repr = MpvNodeMap {
102 _original: PhantomData,
103 _owned_reprs: Vec::with_capacity(self.len()),
104 _flat_reprs: Vec::with_capacity(self.len()),
105 _owned_keys: Vec::with_capacity(self.len()),
106 _flat_keys: Vec::with_capacity(self.len()),
107 node_list: Box::new(mpv_node_list {
108 num: self.len() as c_int,
109 values: null_mut(),
110 keys: null_mut(),
111 }),
112 };
113
114 for (key, value) in self {
115 let cstring = CString::new(key.as_bytes()).unwrap_or_default();
117 repr._flat_keys.push(cstring.as_ptr());
118 repr._owned_keys.push(cstring);
119
120 let val_repr = value.to_mpv_repr();
121 repr._flat_reprs.push(*val_repr.node);
122 repr._owned_reprs.push(val_repr);
123 }
124
125 repr.node_list.values = repr._flat_reprs.as_ptr() as *mut _;
126 repr.node_list.keys = repr._flat_keys.as_ptr() as *mut _;
127
128 repr
129 }
130}