stardust_xr_fusion/
node.rs

1//! The base of all objects in Stardust.
2
3use crate::client::ClientHandle;
4use serde::{Serialize, de::DeserializeOwned};
5use stardust_xr::{
6	messenger::MessengerError,
7	scenegraph::ScenegraphError,
8	schemas::flex::{
9		FlexSerializeError, deserialize, flexbuffers::DeserializationError, serialize,
10	},
11};
12use std::{fmt::Debug, os::fd::OwnedFd, sync::Arc, vec::Vec};
13use thiserror::Error;
14
15pub use crate::protocol::node::*;
16
17pub type NodeResult<O> = Result<O, NodeError>;
18
19#[derive(Error, Debug)]
20pub enum NodeError {
21	#[error("client has been dropped")]
22	ClientDropped,
23	#[error("Messenger error: {e}")]
24	MessengerError { e: MessengerError },
25	#[error("Node does not exist anymore")]
26	DoesNotExist,
27	#[error("Node's signal/method isn't available because it is an alias node")]
28	NotAliased,
29	#[error("invalid path")]
30	InvalidPath,
31	#[error("Serialization failed with an error: {e}")]
32	Serialization { e: FlexSerializeError },
33	#[error("Deserialization failed with an error: {e}")]
34	Deserialization { e: DeserializationError },
35	/// The server returned an error on a method return.
36	#[error("Server returned an error: {e}")]
37	ReturnedError { e: String },
38	#[error("Attempted to register to a singleton twice")]
39	OverrideSingleton,
40	/// The given data is not a valid flexbuffer map.
41	#[error("Map is not a valid flexbuffer map at the root")]
42	MapInvalid,
43}
44impl From<MessengerError> for NodeError {
45	fn from(e: MessengerError) -> Self {
46		NodeError::MessengerError { e }
47	}
48}
49impl From<FlexSerializeError> for NodeError {
50	fn from(e: FlexSerializeError) -> Self {
51		NodeError::Serialization { e }
52	}
53}
54impl From<DeserializationError> for NodeError {
55	fn from(e: DeserializationError) -> Self {
56		NodeError::Deserialization { e }
57	}
58}
59impl From<String> for NodeError {
60	fn from(e: String) -> Self {
61		NodeError::ReturnedError { e }
62	}
63}
64impl From<NodeError> for ScenegraphError {
65	fn from(e: NodeError) -> Self {
66		ScenegraphError::MemberError {
67			error: e.to_string(),
68		}
69	}
70}
71
72/// Common methods all nodes share, to make them easier to use.
73// #[enum_dispatch(FieldType)]
74pub trait NodeType: Sized + Send + Sync + 'static {
75	/// Get a reference to the node.
76	fn node(&self) -> &NodeCore;
77	// What's the node's ID? (used for comparison)
78	fn id(&self) -> u64 {
79		self.node().id
80	}
81	/// Try to get the client
82	fn client(&self) -> &Arc<ClientHandle> {
83		&self.node().client
84	}
85	/// Set whether the node is active or not. This has different effects depending on the node.
86	fn set_enabled(&self, enabled: bool) -> Result<(), NodeError> {
87		if self.node().owned {
88			OwnedAspect::set_enabled(self.node(), enabled)
89		} else {
90			Err(NodeError::DoesNotExist)
91		}
92	}
93}
94
95pub struct NodeCore {
96	pub client: Arc<ClientHandle>,
97	pub id: u64,
98	pub(crate) owned: bool,
99}
100impl NodeCore {
101	pub(crate) fn new(client: Arc<ClientHandle>, id: u64, owned: bool) -> Self {
102		Self { client, id, owned }
103	}
104
105	/// Send a signal directly - no weak reference upgrade!
106	pub(crate) fn send_signal<S: Serialize>(
107		&self,
108		aspect: u64,
109		signal: u64,
110		data: &S,
111		fds: Vec<OwnedFd>,
112	) -> Result<(), NodeError> {
113		let serialized = serialize(data).map_err(|e| NodeError::Serialization { e })?;
114		self.client
115			.message_sender_handle
116			.signal(self.id, aspect, signal, &serialized, fds)
117			.map_err(|e| match e {
118				MessengerError::ReceiverDropped => NodeError::ClientDropped,
119				other => NodeError::MessengerError { e: other },
120			})
121	}
122
123	/// Execute a method directly - no weak reference upgrade!
124	pub(crate) async fn call_method<S: Serialize, D: DeserializeOwned>(
125		&self,
126		aspect: u64,
127		method: u64,
128		data: &S,
129		fds: Vec<OwnedFd>,
130	) -> Result<D, NodeError> {
131		let serialized = serialize(data).map_err(|e| NodeError::Serialization { e })?;
132
133		let response = self
134			.client
135			.message_sender_handle
136			.method(self.id, aspect, method, &serialized, fds)
137			.await
138			.map_err(|e| match e {
139				MessengerError::ReceiverDropped => NodeError::ClientDropped,
140				other => NodeError::MessengerError { e: other },
141			})?
142			.map_err(|e| NodeError::ReturnedError { e })?;
143
144		deserialize(&response.into_message()).map_err(|e| NodeError::Deserialization { e })
145	}
146}
147impl NodeType for NodeCore {
148	fn node(&self) -> &NodeCore {
149		self
150	}
151}
152impl OwnedAspect for NodeCore {}
153impl std::fmt::Debug for NodeCore {
154	fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
155		f.debug_struct("NodeCore")
156			.field("id", &self.id)
157			.field("owned", &self.owned)
158			.finish()
159	}
160}
161impl Drop for NodeCore {
162	fn drop(&mut self) {
163		if self.owned {
164			let _ = self.destroy();
165		}
166	}
167}
168
169// impl NodeType for Node {
170// 	fn node(&self) -> &Node {
171// 		self
172// 	}
173// }
174// impl serde::Serialize for Node {
175// 	fn serialize<S: Serializer>(&self, serializer: S) -> Result<S::Ok, S::Error> {
176// 		serializer.serialize_u64(self.core.id)
177// 	}
178// }
179// impl Debug for Node {
180// 	fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
181// 		let mut dbg = f.debug_struct("Node");
182// 		dbg.field("id", &self.core.id)
183// 			.field("aspects", &self.aspects);
184// 		dbg.finish()
185// 	}
186// }
187// impl Hash for Node {
188// 	fn hash<H: std::hash::Hasher>(&self, state: &mut H) {
189// 		self.core.id.hash(state)
190// 	}
191// }
192// impl PartialEq for Node {
193// 	fn eq(&self, other: &Self) -> bool {
194// 		self.core.id.eq(&other.core.id)
195// 	}
196// }
197// impl Eq for Node {}