oc_wasm_safe/
component.rs

1//! Types related to examining and calling methods on components attached to or installed in a
2//! computer.
3//!
4//! Some of the APIs in this module are independent and can be used standalone. Invoking methods,
5//! however, is more complicated, and must be done as follows:
6//!
7//! 1. Call [`Invoker::take`] if not already done (this can only be done once at program startup)
8//!    to obtain an [`Invoker`].
9//! 2. Call one of the methods on the [`Invoker`] to start the component call. On success, this
10//!    returns an [`InvokeResult`] indicating whether the call is complete or not along with a
11//!    [`MethodCall`] to use to fetch the result.
12//! 3. If necessary, wait until the call is complete by returning from `run`.
13//! 4. If necessary, call [`MethodCall::end_length`] to allocate a sufficient buffer to hold the
14//!    result.
15//! 5. Call one of the methods on [`MethodCall`] to fetch the result, which both fills the provided
16//!    buffer and also returns an [`InvokeEndResult`].
17//! 6. If [`Done`](InvokeEndResult::Done) is returned with an `Ok` result, examine the result in
18//!    the buffer.
19//! 7. If [`Done`](InvokeEndResult::Done) is returned with an `Err` result, the
20//!    [`MethodCallError`] can be examined to determine the reason for the failure, including
21//!    detailed exception information in the form of a [`LastException`] object if applicable.
22//! 8. Another method call can only be started once the [`InvokeResult`], [`MethodCall`],
23//!    [`InvokeEndResult`], and [`LastException`] have all been dropped. This is enforced by means
24//!    of lifetime bindings between those types and the [`Invoker`], preventing the latter from
25//!    being reused too early.
26
27use super::descriptor::AsDescriptor;
28use super::error::{Error, Result};
29use super::helpers::{call_buffer_len, call_buffer_str, call_string};
30use super::Address;
31use crate::panic_or_trap;
32use core::convert::TryFrom;
33use core::fmt::{Display, Formatter};
34use core::marker::PhantomData;
35use core::num::NonZeroUsize;
36use core::ptr;
37use core::sync::atomic::{AtomicBool, Ordering};
38use oc_wasm_sys::component as sys;
39
40/// An object that is capable of listing components attached to the computer.
41///
42/// Because only one component listing can be in progress at a time, only one value of this type
43/// can exist. An application written as a state machine should take the instance and store it in a
44/// `static` variable. An application using `async` and `await` in which only one task needs to
45/// list components should either take the value in that task, or take it in the top-level task and
46/// move it into the task that needs it. An application using `async` and `await` in which multiple
47/// tasks all need to list components needs to arrange mutual exclusion so that only one task can
48/// access the lister at a time.
49pub struct Lister(());
50
51impl Lister {
52	/// Returns the lister.
53	///
54	/// This function can only be called once in the lifetime of the application. On the second and
55	/// subsequent calls, it will return `None`.
56	#[must_use = "A Lister can only be taken once. It needs to be saved. Discarding it means it is impossible to ever list components."]
57	pub fn take() -> Option<Self> {
58		static TAKEN: AtomicBool = AtomicBool::new(false);
59		if TAKEN.swap(true, Ordering::Relaxed) {
60			None
61		} else {
62			Some(Self(()))
63		}
64	}
65
66	/// Begins listing the components attached to the computer.
67	///
68	/// The `component_type` parameter, if present, restricts the listing to only return components
69	/// of the specified type. If the parameter is absent, all components are returned.
70	///
71	/// # Panics
72	/// This function panics if the underlying syscall fails, because the only reasons it could
73	/// fail should be impossible due to the type system.
74	#[allow(clippy::unused_self)] // Not used for its value, but used for its lifetime.
75	pub fn start<'lister>(&'lister mut self, component_type: Option<&str>) -> Listing<'lister> {
76		let result =
77			// SAFETY: list_start permits null or a string pointer/length pair.
78			unsafe{call_string(sys::list_start, component_type)};
79		// Can’t fail because list_start can only fail due to MemoryFault or StringDecode, and
80		// Error::from_i32 already treats those as unreachable.
81		result.unwrap_or_else(|_| panic_or_trap!("unreachable"));
82		Listing(PhantomData)
83	}
84}
85
86/// An in-progress component listing.
87///
88/// The `'lister` lifetime parameter is the lifetime of the component lister that is performing the
89/// listing.
90#[must_use = "Starting a component listing is only useful if you read the results."]
91pub struct Listing<'lister>(PhantomData<&'lister mut Lister>);
92
93impl<'lister> Listing<'lister> {
94	/// Returns the next entry in the list of components.
95	///
96	/// If there is a next entry, its UUID is return. If not, `None` is returned.
97	///
98	/// # Panics
99	/// * This function panics if the underlying syscall fails, because the only reasons it could
100	///   fail should be impossible due to the type system.
101	/// * This function panics if there is a mismatch between OC-Wasm-safe’s and OpenComputers’s
102	///   ideas of the length or formatting of a component address.
103	#[allow(clippy::should_implement_trait)] // It’s very like Iterator::next, but can’t be due to lifetimes.
104	#[allow(clippy::unused_self)] // Not used for its value, but used for its lifetime.
105	pub fn next<'listing>(&'listing mut self) -> Option<ListEntry<'listing, 'lister>> {
106		// SAFETY: list_next permits a writeable buffer pointer and promises to always write a
107		// valid UUID. It can only fail due to MemoryFault, which, because we provide it with a
108		// valid buffer, is impossible. However we care whether its return value is 0 or 1.
109		let mut buf = uuid::Bytes::default();
110		let rc = unsafe { sys::list_next(buf.as_mut_ptr()) };
111		if rc == 0 {
112			None
113		} else {
114			let address = Address::from_bytes(buf);
115			Some(ListEntry {
116				address,
117				listing: PhantomData,
118			})
119		}
120	}
121}
122
123/// A single in from a listing.
124///
125/// The `'lister` lifetime parameter is the lifetime of the component lister. The `'listing`
126/// lifetime parameter is the lifetime of the specific listing being performed.
127#[derive(Debug)]
128pub struct ListEntry<'listing, 'lister> {
129	/// The component address.
130	address: Address,
131
132	/// A phantom that allows the `'listing` lifetime to be recorded.
133	listing: PhantomData<&'listing mut Listing<'lister>>,
134}
135
136impl ListEntry<'_, '_> {
137	/// Returns the address of the component.
138	#[must_use = "This function is only useful for its return value"]
139	pub fn address(&self) -> &Address {
140		&self.address
141	}
142
143	/// Returns the length, in bytes, of the component’s type.
144	///
145	/// # Panics
146	/// * This function panics if the underlying syscall fails, because the only reasons it could
147	///   fail should be impossible due to the type system.
148	#[allow(clippy::unused_self)] // Not used for its value, but used for its lifetime.
149	#[must_use = "This function is only useful for its return value"]
150	pub fn type_name_len(&self) -> NonZeroUsize {
151		// SAFETY: list_type permits null.
152		let len = unsafe { call_buffer_len(sys::list_type) }
153			.unwrap_or_else(|_| panic_or_trap!("unreachable"));
154		// SAFETY: A component type can’t be empty.
155		unsafe { NonZeroUsize::new_unchecked(len) }
156	}
157
158	/// Returns the type of the most recently listed component.
159	///
160	/// The `buffer` parameter identifies where to store the component type.
161	///
162	/// The type is written to `buffer` and a string slice referring to it is returned.
163	///
164	/// # Errors
165	/// * [`BufferTooShort`](Error::BufferTooShort) is returned if `buffer` is provided but is not
166	///   large enough to hold the component type.
167	#[allow(clippy::unused_self)] // Not used for its value, but used for its lifetime.
168	#[must_use = "This function is only useful for its return value"]
169	pub fn type_name<'buffer>(&self, buffer: &'buffer mut [u8]) -> Result<&'buffer mut str> {
170		// SAFETY: list_type permits a writeable buffer pointer/length pair and promises to always
171		// write a valid UTF-8 string and return its length.
172		unsafe { call_buffer_str(sys::list_type, buffer) }
173	}
174}
175
176/// Returns the length, in bytes, of the type of a component.
177///
178/// The `address` parameter identifies the component by its UUID.
179///
180/// # Errors
181/// * [`NoSuchComponent`](Error::NoSuchComponent) is returned if the component does not exist or is
182///   inaccessible.
183#[allow(clippy::module_name_repetitions)] // For parallelism with component_type
184#[must_use = "This function is only useful for its return value"]
185pub fn component_type_len(address: &Address) -> Result<NonZeroUsize> {
186	let address = address.as_bytes();
187	let len = Error::from_isize(
188		// SAFETY: component_type permits a UUID input pointer and null output pointer/length pair.
189		unsafe { sys::component_type(address.as_ptr(), ptr::null_mut(), 0) },
190	)?;
191	// SAFETY: A component type can’t be empty.
192	Ok(unsafe { NonZeroUsize::new_unchecked(len) })
193}
194
195/// Returns the type of a component.
196///
197/// The `address` parameter identifies the component by its UUID. The `buffer` parameter identifies
198/// where to store the component type.
199///
200/// The type is written into `buffer` and a string slice referring to it is returned.
201///
202/// # Errors
203/// * [`BufferTooShort`](Error::BufferTooShort) is returned if `buffer` is provided but is not
204///   large enough to hold the component type.
205/// * [`NoSuchComponent`](Error::NoSuchComponent) is returned if the component does not exist or is
206///   inaccessible.
207#[allow(clippy::module_name_repetitions)] // Because just “type” would be a keyword
208#[must_use = "This function is only useful for its return value"]
209pub fn component_type<'buf>(address: &Address, buffer: &'buf mut [u8]) -> Result<&'buf mut str> {
210	let address = address.as_bytes();
211	let bytes_written = {
212		let buf_len = buffer.len();
213		let buf_ptr = buffer.as_mut_ptr();
214		Error::from_isize(
215			// SAFETY: component_type permits a UUID input pointer and a writeable buffer output
216			// pointer/length pair.
217			unsafe { sys::component_type(address.as_ptr(), buf_ptr, buf_len) },
218		)?
219	};
220	Ok(
221		// SAFETY: component_type promises to always write a valid UTF-8 string and return its
222		// length.
223		unsafe { core::str::from_utf8_unchecked_mut(buffer.get_unchecked_mut(0..bytes_written)) },
224	)
225}
226
227/// Returns the slot that a component is installed into.
228///
229/// The `address` parameter identifies the component by its UUID.
230///
231/// # Errors
232/// * [`NoSuchComponent`](Error::NoSuchComponent) is returned if the component does not exist or is
233///   inaccessible.
234/// * [`Other`](Error::Other) is returned if the component exists but is not installed in a slot.
235#[must_use = "This function is only useful for its return value"]
236pub fn slot(address: &Address) -> Result<u32> {
237	let address = address.as_bytes();
238	Error::from_i32(
239		// SAFETY: slot permits a UUID input pointer.
240		unsafe { sys::slot(address.as_ptr()) },
241	)
242}
243
244/// An object that is capable of listing methods on a component or opaque value.
245///
246/// Because only one method listing can be in progress at a time, only one value of this type can
247/// exist. An application written as a state machine should take the instance and store it in a
248/// `static` variable. An application using `async` and `await` in which only one task needs to
249/// list methods should either take the value in that task, or take it in the top-level task and
250/// move it into the task that needs it. An application using `async` and `await` in which multiple
251/// tasks all need to list methods needs to arrange mutual exclusion so that only one task can
252/// access the lister at a time.
253pub struct MethodLister(());
254
255impl MethodLister {
256	/// Returns the lister.
257	///
258	/// This function can only be called once in the lifetime of the application. On the second and
259	/// subsequent calls, it will return `None`.
260	#[must_use = "A Lister can only be taken once. It needs to be saved. Discarding it means it is impossible to ever list methods."]
261	pub fn take() -> Option<Self> {
262		static TAKEN: AtomicBool = AtomicBool::new(false);
263		if TAKEN.swap(true, Ordering::Relaxed) {
264			None
265		} else {
266			Some(Self(()))
267		}
268	}
269
270	/// Begins iteration over the methods available on a component.
271	///
272	/// The `address` parameter identifies the component by its UUID.
273	///
274	/// # Errors
275	/// * [`NoSuchComponent`](Error::NoSuchComponent) is returned if the component does not exist
276	///   or is inaccessible.
277	#[allow(clippy::module_name_repetitions)] // Important to distinguish from methods_start_value
278	#[allow(clippy::unused_self)] // Not used for its value, but used for its lifetime.
279	pub fn start_component<'lister>(
280		&'lister mut self,
281		address: &Address,
282	) -> Result<MethodListing<'lister>> {
283		let address = address.as_bytes();
284		// SAFETY: methods_start_component permits an input UUID pointer.
285		Error::from_i32(unsafe { sys::methods_start_component(address.as_ptr()) })?;
286		Ok(MethodListing(PhantomData))
287	}
288
289	/// Begins iteration over the methods available on an opaque value.
290	///
291	/// The `descriptor` parameter identifies the opaque value by its descriptor.
292	///
293	/// Iteration over methods is not reentrant. Concurrent software must ensure that only one method
294	/// iteration at a time is attempted. This is even true if different components are involved, or if
295	/// one is over a component and the other over an opaque value.
296	#[allow(clippy::unused_self)] // Not used for its value, but used for its lifetime.
297	pub fn start_value(&mut self, descriptor: &impl AsDescriptor) -> MethodListing<'_> {
298		// SAFETY: methods_start_value permits a descriptor.
299		// SOUNDNESS: Ignoring the return value is sound because methods_start_value can only fail
300		// due to BadDescriptor, and BadDescriptor cannot happen because the parameter is a
301		// Descriptor object.
302		unsafe { sys::methods_start_value(descriptor.as_descriptor().as_raw()) };
303		MethodListing(PhantomData)
304	}
305}
306
307/// The possible attributes of a method.
308#[derive(Clone, Copy, Debug, Eq, Hash, PartialEq)]
309pub struct MethodAttributes {
310	/// The method is direct.
311	///
312	/// If this value is `true`, the method can be called and completed within a single timeslice.
313	/// The caller cannot assume that every invocation of a direct method will complete within a
314	/// timeslice, as even direct calls may have call budget limits; however, if this value is
315	/// `false`, then no call to the method will ever complete immediately.
316	pub direct: bool,
317
318	/// The method is a property getter.
319	///
320	/// If this value is `true`, the method conceptually reads the value of a property, rather than
321	/// performing an action.
322	pub getter: bool,
323
324	/// The method is a property setter.
325	///
326	/// If this value is `true`, the method conceptually writes the value of a property, rather
327	/// than performing an action.
328	pub setter: bool,
329}
330
331impl From<u32> for MethodAttributes {
332	fn from(value: u32) -> Self {
333		Self {
334			direct: (value & 1) != 0,
335			getter: (value & 2) != 0,
336			setter: (value & 4) != 0,
337		}
338	}
339}
340
341#[must_use = "Starting a method listing is only useful if you read the results."]
342pub struct MethodListing<'lister>(PhantomData<&'lister mut MethodLister>);
343
344impl MethodListing<'_> {
345	/// Returns the length, in bytes, of the name of the next method in the list of methods.
346	///
347	/// If there is no next entry, `None` is returned.
348	///
349	/// # Panics
350	/// This function panics if the underlying syscall fails, because the only reasons it could
351	/// fail should be impossible due to the type system.
352	#[allow(clippy::unused_self)] // Not used for its value, but used for its lifetime.
353	#[must_use = "This function is only useful for its return value"]
354	pub fn next_len(&self) -> Option<NonZeroUsize> {
355		let result = Error::from_isize(
356			// SAFETY: methods_next permits null for both pointers.
357			unsafe { sys::methods_next(ptr::null_mut(), 0, ptr::null_mut()) },
358		);
359		// Can’t fail because methods_next can only fail due to MemoryFault or StringDecode, and
360		// Error::from_isize already treats those as unreachable.
361		NonZeroUsize::new(result.unwrap_or_else(|_| panic_or_trap!("unreachable")))
362	}
363
364	/// Returns the next method in the list of methods.
365	///
366	/// The `buffer` parameter identifies where to store the next method name.
367	///
368	/// If there is a next method, its name is written to `buffer`, a string slice referring to the
369	/// name along with the attributes are returned, and the iteration is advanced. If not, `None`
370	/// is returned.
371	///
372	/// # Errors
373	/// * [`BufferTooShort`](Error::BufferTooShort) is returned if `buffer` is not large enough to
374	///   hold the method name.
375	///
376	/// On error, the iteration does not advance.
377	#[allow(clippy::unused_self)] // Not used for its value, but used for its lifetime.
378	pub fn next<'buffer>(
379		&mut self,
380		buffer: &'buffer mut [u8],
381	) -> Result<Option<(&'buffer mut str, MethodAttributes)>> {
382		let mut attributes = 0_u32;
383		let bytes_written = {
384			let len = buffer.len();
385			let ptr = buffer.as_mut_ptr();
386			Error::from_isize(
387				// SAFETY: methods_next permits a writeable buffer pointer/length pair and a pointer to
388				// a single i32 attributes bitmask.
389				unsafe { sys::methods_next(ptr, len, &mut attributes) },
390			)?
391		};
392		if bytes_written == 0 {
393			Ok(None)
394		} else {
395			Ok(Some((
396				// SAFETY: methods_next promises to always write a valid UTF-8 string and return its
397				// length.
398				unsafe {
399					core::str::from_utf8_unchecked_mut(buffer.get_unchecked_mut(0..bytes_written))
400				},
401				attributes.into(),
402			)))
403		}
404	}
405}
406
407/// Returns the length, in bytes, of the documentation for a method on a component.
408///
409/// The `address` parameter identifies the component by its UUID. The `method` parameter identifies
410/// the method by its name.
411///
412/// # Errors
413/// * [`NoSuchComponent`](Error::NoSuchComponent) is returned if the component does not exist or is
414///   inaccessible.
415/// * [`NoSuchMethod`](Error::NoSuchMethod) is returned if the method does not exist on the
416///   component.
417#[must_use = "This function is only useful for its return value"]
418pub fn documentation_component_length(address: &Address, method: &str) -> Result<usize> {
419	let address = address.as_bytes();
420	Error::from_isize(
421		// SAFETY: documentation_component permits an input address UUID pointer and method name
422		// string pointer/length pair, and a null output pointer/length pair.
423		unsafe {
424			sys::documentation_component(
425				address.as_ptr(),
426				method.as_ptr(),
427				method.len(),
428				ptr::null_mut(),
429				0,
430			)
431		},
432	)
433}
434
435/// Returns the documentation for a method on a component.
436///
437/// The `address` parameter identifies the component by its UUID. The `method` parameter identifies
438/// the method by its name. The `buffer` parameter identifies where to store the documentation.
439///
440/// The documentation is written into `buffer` and a string slice referring to it is returned.
441///
442/// # Errors
443/// * [`BufferTooShort`](Error::BufferTooShort) is returned if `buffer` is provided but is not
444///   large enough to hold the documentation.
445/// * [`NoSuchComponent`](Error::NoSuchComponent) is returned if the component does not exist or is
446///   inaccessible.
447/// * [`NoSuchMethod`](Error::NoSuchMethod) is returned if the method does not exist on the
448///   component.
449#[allow(clippy::module_name_repetitions)] // Important to distinguish from documentation_value
450#[must_use = "This function is only useful for its return value"]
451pub fn documentation_component<'buf>(
452	address: &Address,
453	method: &str,
454	buffer: &'buf mut [u8],
455) -> Result<&'buf mut str> {
456	let address = address.as_bytes();
457	let bytes_written = {
458		let buf_len = buffer.len();
459		let buf_ptr = buffer.as_mut_ptr();
460		Error::from_isize(
461			// SAFETY: documentation_component permits an input address UUID pointer and method name
462			// string pointer/length pair, and a writeable buffer output pointer/length pair.
463			unsafe {
464				sys::documentation_component(
465					address.as_ptr(),
466					method.as_ptr(),
467					method.len(),
468					buf_ptr,
469					buf_len,
470				)
471			},
472		)?
473	};
474	Ok(
475		// SAFETY: documentation_component promises to always write a valid UTF-8 string and return
476		// its length.
477		unsafe { core::str::from_utf8_unchecked_mut(buffer.get_unchecked_mut(0..bytes_written)) },
478	)
479}
480
481/// Returns the length, in bytes, of the documentation for a method on a value.
482///
483/// The `descriptor` parameter identifies the value by its descriptor. The `method` parameter
484/// identifies the method by its name.
485///
486/// # Errors
487/// * [`NoSuchMethod`](Error::NoSuchMethod) is returned if the method does not exist on the
488///   value.
489#[must_use = "This function is only useful for its return value"]
490pub fn documentation_value_length(descriptor: &impl AsDescriptor, method: &str) -> Result<usize> {
491	Error::from_isize(
492		// SAFETY: documentation_value permits two string pointer/length pairs and a null.
493		unsafe {
494			sys::documentation_value(
495				descriptor.as_descriptor().as_raw(),
496				method.as_ptr(),
497				method.len(),
498				ptr::null_mut(),
499				0,
500			)
501		},
502	)
503}
504
505/// Returns the documentation for a method on a value.
506///
507/// The `descriptor` parameter identifies the value by its descriptor. The `method` parameter
508/// identifies the method by its name. The `buffer` parameter identifies where to store the
509/// documentation.
510///
511/// The documentation is written into `buffer` and a string slice referring to it is returned.
512///
513/// # Errors
514/// * [`BufferTooShort`](Error::BufferTooShort) is returned if `buffer` is provided but is not
515///   large enough to hold the documentation.
516/// * [`NoSuchMethod`](Error::NoSuchMethod) is returned if the method does not exist on the value.
517#[must_use = "This function is only useful for its return value"]
518pub fn documentation_value<'buf>(
519	descriptor: &impl AsDescriptor,
520	method: &str,
521	buffer: &'buf mut [u8],
522) -> Result<&'buf mut str> {
523	let bytes_written = {
524		let buf_len = buffer.len();
525		let buf_ptr = buffer.as_mut_ptr();
526		Error::from_isize(
527			// SAFETY: documentation_value permits two string pointer/length pairs and a writeable
528			// buffer pointer/length pair.
529			unsafe {
530				sys::documentation_value(
531					descriptor.as_descriptor().as_raw(),
532					method.as_ptr(),
533					method.len(),
534					buf_ptr,
535					buf_len,
536				)
537			},
538		)?
539	};
540	Ok(
541		// SAFETY: documentation_value promises to always write a valid UTF-8 string and return its
542		// length.
543		unsafe { core::str::from_utf8_unchecked_mut(buffer.get_unchecked_mut(0..bytes_written)) },
544	)
545}
546
547/// An object that is capable of invoking methods.
548///
549/// Because only one method can be invoked at a time, only one value of this type can exist. An
550/// application written as a state machine should take the instance and store it in a `static`
551/// variable. An application using `async` and `await` in which only one task needs to make method
552/// calls should either take the value in that task, or take it in the top-level task and move it
553/// into the task that needs it. An application using `async` and `await` in which multiple tasks
554/// all need to make method calls needs to arrange mutual exclusion so that only one task can
555/// access the invoker at a time.
556pub struct Invoker(());
557
558impl Invoker {
559	/// Returns the invoker.
560	///
561	/// This function can only be called once in the lifetime of the application. On the second and
562	/// subsequent calls, it will return `None`.
563	#[must_use = "An Invoker can only be taken once. It needs to be saved. Discarding it means it is impossible to ever make a method call."]
564	pub fn take() -> Option<Self> {
565		static TAKEN: AtomicBool = AtomicBool::new(false);
566		if TAKEN.swap(true, Ordering::Relaxed) {
567			None
568		} else {
569			Some(Self(()))
570		}
571	}
572
573	/// Starts invoking a method on a component.
574	///
575	/// The `address` parameter identifies the component by its UUID. The `method` parameter
576	/// identifies the method by its name. The `params` parameter, if present, contains a
577	/// CBOR-encoded array of parameters to pass to the method.
578	///
579	/// # Errors
580	/// * [`CborDecode`](Error::CborDecode) is returned if the `params` parameter is present but
581	///   contains an invalid or unsupported CBOR sequence.
582	/// * [`BadDescriptor`](Error::BadDescriptor) is returned if the parameters contain a
583	///   descriptor reference to a descriptor that is not open.
584	/// * [`TooManyDescriptors`](Error::TooManyDescriptors) is returned if the descriptor table is
585	///   too full and some descriptors must be closed before another method call can be made.
586	#[allow(clippy::unused_self)] // Not used for its value, but used for its lifetime.
587	pub fn component_method<'invoker>(
588		&'invoker mut self,
589		address: &Address,
590		method: &str,
591		params: Option<&[u8]>,
592	) -> Result<(InvokeResult, MethodCall<'invoker>)> {
593		let address = address.as_bytes();
594		let params_ptr = params.map_or(ptr::null(), <[u8]>::as_ptr);
595		let done = Error::from_i32(
596			// SAFETY: invoke_component_method permits an input UUID pointer, method name
597			// pointer/length pair, and CBOR pointer which may be null.
598			unsafe {
599				sys::invoke_component_method(
600					address.as_ptr(),
601					method.as_ptr(),
602					method.len(),
603					params_ptr,
604				)
605			},
606		)? != 0;
607		Ok((
608			if done {
609				InvokeResult::Complete
610			} else {
611				InvokeResult::Incomplete
612			},
613			MethodCall(PhantomData),
614		))
615	}
616
617	/// Starts invoking a callable opaque value.
618	///
619	/// The `descriptor` parameter identifies the opaque value by its descriptor. The `params`
620	/// parameter, if present, contains a CBOR-encoded array of parameters to pass to the method.
621	///
622	/// # Errors
623	/// * [`CborDecode`](Error::CborDecode) is returned if the `params` parameter is present but
624	///   contains an invalid or unsupported CBOR sequence.
625	/// * [`BadDescriptor`](Error::BadDescriptor) is returned if the parameters contain a
626	///   descriptor reference to a descriptor that is not open.
627	/// * [`TooManyDescriptors`](Error::TooManyDescriptors) is returned if the descriptor table is
628	///   too full and some descriptors must be closed before another method call can be made.
629	#[allow(clippy::unused_self)] // Not used for its value, but used for its lifetime.
630	pub fn value<'invoker>(
631		&'invoker mut self,
632		descriptor: &impl AsDescriptor,
633		params: Option<&[u8]>,
634	) -> Result<(InvokeResult, MethodCall<'invoker>)> {
635		let params_ptr = params.map_or(ptr::null(), <[u8]>::as_ptr);
636		let done = Error::from_i32(
637			// SAFETY: invoke_value permits any descriptor and a CBOR pointer which may be null.
638			unsafe { sys::invoke_value(descriptor.as_descriptor().as_raw(), params_ptr) },
639		)? != 0;
640		Ok((
641			if done {
642				InvokeResult::Complete
643			} else {
644				InvokeResult::Incomplete
645			},
646			MethodCall(PhantomData),
647		))
648	}
649
650	/// Starts reading from an index of an opaque value.
651	///
652	/// The `descriptor` parameter identifies the opaque value by its descriptor. The `params`
653	/// parameter, if present, contains a CBOR-encoded array of parameters to use for indexing.
654	///
655	/// # Errors
656	/// * [`CborDecode`](Error::CborDecode) is returned if the `params` parameter is present but
657	///   contains an invalid or unsupported CBOR sequence.
658	/// * [`BadDescriptor`](Error::BadDescriptor) is returned if the parameters contain a
659	///   descriptor reference to a descriptor that is not open.
660	/// * [`TooManyDescriptors`](Error::TooManyDescriptors) is returned if the descriptor table is
661	///   too full and some descriptors must be closed before another method call can be made.
662	#[allow(clippy::unused_self)] // Not used for its value, but used for its lifetime.
663	pub fn value_indexed_read<'invoker>(
664		&'invoker mut self,
665		descriptor: &impl AsDescriptor,
666		params: Option<&[u8]>,
667	) -> Result<(InvokeResult, MethodCall<'invoker>)> {
668		let params_ptr = params.map_or(ptr::null(), <[u8]>::as_ptr);
669		let done = Error::from_i32(
670			// SAFETY: invoke_value_indexed_read permits any descriptor and a CBOR pointer which
671			// may be null.
672			unsafe {
673				sys::invoke_value_indexed_read(descriptor.as_descriptor().as_raw(), params_ptr)
674			},
675		)? != 0;
676		Ok((
677			if done {
678				InvokeResult::Complete
679			} else {
680				InvokeResult::Incomplete
681			},
682			MethodCall(PhantomData),
683		))
684	}
685
686	/// Starts writing to an index of an opaque value.
687	///
688	/// The `descriptor` parameter identifies the opaque value by its descriptor. The `params`
689	/// parameter, if present, contains a CBOR-encoded array of parameters to use for indexing and
690	/// the value to write.
691	///
692	/// # Errors
693	/// * [`CborDecode`](Error::CborDecode) is returned if the `params` parameter is present but
694	///   contains an invalid or unsupported CBOR sequence.
695	/// * [`BadDescriptor`](Error::BadDescriptor) is returned if the parameters contain a
696	///   descriptor reference to a descriptor that is not open.
697	/// * [`TooManyDescriptors`](Error::TooManyDescriptors) is returned if the descriptor table is
698	///   too full and some descriptors must be closed before another method call can be made.
699	#[allow(clippy::unused_self)] // Not used for its value, but used for its lifetime.
700	pub fn value_indexed_write<'invoker>(
701		&'invoker mut self,
702		descriptor: &impl AsDescriptor,
703		params: Option<&[u8]>,
704	) -> Result<(InvokeResult, MethodCall<'invoker>)> {
705		let params_ptr = params.map_or(ptr::null(), <[u8]>::as_ptr);
706		let done = Error::from_i32(
707			// SAFETY: invoke_value_indexed_write permits any descriptor and a CBOR pointer which
708			// may be null.
709			unsafe {
710				sys::invoke_value_indexed_write(descriptor.as_descriptor().as_raw(), params_ptr)
711			},
712		)? != 0;
713		Ok((
714			if done {
715				InvokeResult::Complete
716			} else {
717				InvokeResult::Incomplete
718			},
719			MethodCall(PhantomData),
720		))
721	}
722
723	/// Starts invoking a method on an opaque value.
724	///
725	/// The `descriptor` parameter identifies the opaque value by its descriptor. The `method`
726	/// parameter identifies the method by its name. The `params` parameter, if present, contains a
727	/// CBOR-encoded array of parameters to pass to the method.
728	///
729	/// # Errors
730	/// * [`CborDecode`](Error::CborDecode) is returned if the `params` parameter is present but
731	///   contains an invalid or unsupported CBOR sequence.
732	/// * [`BadDescriptor`](Error::BadDescriptor) is returned if the parameters contain a
733	///   descriptor reference to a descriptor that is not open.
734	/// * [`TooManyDescriptors`](Error::TooManyDescriptors) is returned if the descriptor table is
735	///   too full and some descriptors must be closed before another method call can be made.
736	#[allow(clippy::unused_self)] // Not used for its value, but used for its lifetime.
737	pub fn value_method<'invoker>(
738		&'invoker mut self,
739		descriptor: &impl AsDescriptor,
740		method: &str,
741		params: Option<&[u8]>,
742	) -> Result<(InvokeResult, MethodCall<'invoker>)> {
743		let params_ptr = params.map_or(ptr::null(), <[u8]>::as_ptr);
744		let done = Error::from_i32(
745			// SAFETY: invoke_value_method permits any descriptor, a string pointer/length pair, and a
746			// CBOR pointer which may be null.
747			unsafe {
748				sys::invoke_value_method(
749					descriptor.as_descriptor().as_raw(),
750					method.as_ptr(),
751					method.len(),
752					params_ptr,
753				)
754			},
755		)? != 0;
756		Ok((
757			if done {
758				InvokeResult::Complete
759			} else {
760				InvokeResult::Incomplete
761			},
762			MethodCall(PhantomData),
763		))
764	}
765}
766
767impl core::fmt::Debug for Invoker {
768	fn fmt(&self, f: &mut Formatter<'_>) -> core::fmt::Result {
769		write!(f, "Invoker")
770	}
771}
772
773impl PartialEq for Invoker {
774	fn eq(&self, _: &Self) -> bool {
775		// Only one invoker can ever exist, therefore all invokers that exist are equal.
776		true
777	}
778}
779
780impl Eq for Invoker {}
781
782/// The possible results of a successful start to a method call.
783#[derive(Clone, Copy, Debug, Eq, Hash, Ord, PartialEq, PartialOrd)]
784pub enum InvokeResult {
785	/// The method is complete and its result can be fetched immediately.
786	Complete,
787
788	/// The method is not finished yet; its result can be fetched on the next timeslice.
789	Incomplete,
790}
791
792/// An in-progress method call.
793///
794/// The `'invoker` lifetime parameter is the lifetime of the method invoker that is performing the
795/// call.
796///
797/// If a value of this type is dropped, the method call is cancelled. If it has not executed yet,
798/// it will not execute; if it has already executed, its result is discarded.
799#[derive(Debug, Eq, PartialEq)]
800#[must_use = "Discarding a MethodCall immediately is buggy. Even if you know the method you are calling is direct and don’t need its return value, direct methods must be run indirectly if the method call cost limit is reached, so you still need to make sure it finishes."]
801pub struct MethodCall<'invoker>(PhantomData<&'invoker mut Invoker>);
802
803impl<'invoker> MethodCall<'invoker> {
804	/// Returns the length, in bytes, of the result of the method call, or an indication that the
805	/// call is not finished.
806	///
807	/// On success, the length and the `MethodCall` are returned, allowing the `MethodCall` to be
808	/// reused to fetch the actual bytes.
809	///
810	/// # Errors
811	/// * [`NoSuchComponent`](Error::NoSuchComponent) is returned if the method call failed because
812	///   the component does not exist or is inaccessible.
813	/// * [`NoSuchMethod`](Error::NoSuchMethod) is returned if the method call failed because the
814	///   method does not exist on the component.
815	/// * [`BadParameters`](Error::BadParameters) is returned if the parameters provided when
816	///   starting the call are not acceptable for the method.
817	/// * [`Other`](Error::Other) is returned if the method call failed.
818	#[must_use = "This function is only useful for its return value"]
819	pub fn end_length(self) -> InvokeEndLengthResult<'invoker> {
820		// SAFETY: invoke_end permits null.
821		let ret = unsafe { sys::invoke_end(ptr::null_mut(), 0) };
822		match MethodCallError::from_isize(PhantomData, ret) {
823			Ok(n) => InvokeEndLengthResult::Done(Ok((n, self))),
824			Err(MethodCallError::QueueEmpty) => InvokeEndLengthResult::Pending(self),
825			Err(e) => InvokeEndLengthResult::Done(Err(e)),
826		}
827	}
828
829	/// Returns the result of the method call as a CBOR-encoded data item, or an indication that
830	/// the call is not finished.
831	///
832	/// On success, the result is written into up to `len` bytes pointed to by `buffer`, and the
833	/// number of bytes written is returned. If the buffer is not large enough to hold the call
834	/// result, [`BufferTooShort`](InvokeEndResult::BufferTooShort) is returned, containing the
835	/// `MethodCall` object, allowing the caller to retry fetching the results with a larger
836	/// buffer, or call [`end_length`](MethodCall::end_length) to obtain the needed buffer size.
837	///
838	/// # Errors
839	/// * [`NoSuchComponent`](Error::NoSuchComponent) is returned if the method call failed because the
840	///   component does not exist or is inaccessible.
841	/// * [`NoSuchMethod`](Error::NoSuchMethod) is returned if the method call failed because the
842	///   method does not exist on the component.
843	/// * [`BadParameters`](Error::BadParameters) is returned if the parameters provided when
844	///   starting the call are not acceptable for the method.
845	/// * [`Other`](Error::Other) is returned if the method call failed.
846	///
847	/// # Safety
848	/// The caller must ensure that `len` bytes pointed to by `buffer` are writeable.
849	pub unsafe fn end_ptr(self, buffer: *mut u8, len: usize) -> InvokeEndResult<'invoker> {
850		let result = sys::invoke_end(buffer, len);
851		match MethodCallError::from_isize(PhantomData, result) {
852			Err(MethodCallError::BufferTooShort) => InvokeEndResult::BufferTooShort(self),
853			Err(MethodCallError::QueueEmpty) => InvokeEndResult::Pending(self),
854			other => InvokeEndResult::Done(other),
855		}
856	}
857
858	/// Returns the result of the method call as a CBOR-encoded data item, or an indication that
859	/// the call is not finished.
860	///
861	/// On success, the result is written into `buffer`, and the number of bytes written is
862	/// returned. If the buffer is not large enough to hold the call result,
863	/// [`BufferTooShort`](InvokeEndResult::BufferTooShort) is returned, containing the
864	/// `MethodCall` object, allowing the caller to retry fetching the results with a larger
865	/// buffer, or call [`end_length`](MethodCall::end_length) to obtain the needed buffer size.
866	///
867	/// # Errors
868	/// * [`NoSuchComponent`](Error::NoSuchComponent) is returned if the method call failed because the
869	///   component does not exist or is inaccessible.
870	/// * [`NoSuchMethod`](Error::NoSuchMethod) is returned if the method call failed because the
871	///   method does not exist on the component.
872	/// * [`BadParameters`](Error::BadParameters) is returned if the parameters provided when
873	///   starting the call are not acceptable for the method.
874	/// * [`Other`](Error::Other) is returned if the method call failed.
875	pub fn end(self, buffer: &mut [u8]) -> InvokeEndResult<'invoker> {
876		// SAFETY: invoke_end permits a writeable buffer pointer/length pair and promises to always
877		// return the length of data it wrote.
878		let result = unsafe { sys::invoke_end(buffer.as_mut_ptr(), buffer.len()) };
879		match MethodCallError::from_isize(PhantomData, result) {
880			Err(MethodCallError::BufferTooShort) => InvokeEndResult::BufferTooShort(self),
881			Err(MethodCallError::QueueEmpty) => InvokeEndResult::Pending(self),
882			other => InvokeEndResult::Done(other),
883		}
884	}
885}
886
887impl Drop for MethodCall<'_> {
888	fn drop(&mut self) {
889		// SAFETY: invoke_cancel is unconditionally safe.
890		unsafe { sys::invoke_cancel() }
891	}
892}
893
894/// An object that is able to retrieve detailed method call error information.
895///
896/// Certain errors, when returned from a method call (and only from a method call!), are
897/// accompanied by additional detailed error information which is only available until the next
898/// method call. A value of this type uses the `'invoker` lifetime parameter to prevent additional
899/// method calls from being made until the caller has finished examining the detailed error
900/// information.
901#[derive(Clone, Copy, Debug, Eq, Hash, PartialEq)]
902pub struct LastException<'invoker>(PhantomData<&'invoker mut Invoker>);
903
904impl<'invoker> LastException<'invoker> {
905	/// Creates a new `LastException`.
906	fn new(_: PhantomData<&'invoker mut Invoker>) -> Self {
907		Self(PhantomData)
908	}
909
910	/// Returns the length of the human-readable message for the error.
911	///
912	/// # Panics
913	/// This function panics if the underlying syscall fails, because the only reasons it could
914	/// fail should be impossible due to the type system.
915	#[allow(clippy::unused_self)] // Not used for its value, but used for its lifetime.
916	#[must_use = "This function is only useful for its return value"]
917	pub fn message_length(&self) -> usize {
918		// SAFETY: last_exception_message permits null.
919		let result = unsafe { call_buffer_len(sys::last_exception_message) };
920		result.unwrap_or_else(|_| panic_or_trap!("unreachable"))
921	}
922
923	/// Returns the human-readable message for the error.
924	///
925	/// The message is written into `buffer`, and a string slice over the written text is returned.
926	///
927	/// # Errors
928	/// * [`BufferTooShort`](Error::BufferTooShort) is returned if `buffer` is not long enough to
929	///   hold the error message.
930	///
931	/// # Panics
932	/// This function panics if the underlying syscall fails for any reason other than
933	/// [`BufferTooShort`](Error::BufferTooShort), because the only other reasons it could fail
934	/// should be impossible due to the type system.
935	#[allow(clippy::unused_self)] // Not used for its value, but used for its lifetime.
936	pub fn message<'buf>(&self, buffer: &'buf mut [u8]) -> Result<&'buf str> {
937		// SAFETY: last_exception permits a writeable buffer output pointer/length pair and
938		// promises to always write a valid UTF-8 string and return its length.
939		let result = unsafe { call_buffer_str(sys::last_exception_message, buffer) };
940		match result {
941			Ok(message) => Ok(message),
942			Err(Error::BufferTooShort) => Err(Error::BufferTooShort),
943			Err(_) => panic_or_trap!("unreachable"),
944		}
945	}
946
947	/// Checks whether the Java exception underlying the error is of a certain type.
948	///
949	/// The `class` parameter must be the fully qualified name of a Java class (e.g.
950	/// `java.io.IOException`). This function returns `true` if the exception that caused the error
951	/// is `class` or a subclass thereof, or `false` if not.
952	///
953	/// # Panics
954	/// This function panics if the underlying syscall fails, because the only reasons it could
955	/// fail should be impossible due to the type system.
956	#[allow(clippy::unused_self)] // Not used for its value, but used for its lifetime.
957	#[must_use = "This function is only useful for its return value"]
958	pub fn is_type(&self, class: &str) -> bool {
959		// SAFETY: is_type permits a string pointer/length pair.
960		let result = unsafe { call_string(sys::last_exception_is_type, Some(class)) };
961		result.unwrap_or_else(|_| panic_or_trap!("unreachable")) != 0
962	}
963}
964
965/// The possible errors that could occur during a method call.
966///
967/// Some errors carry additional information. This information is only available until the start of
968/// the next method call. The `'invoker` lifetime ensures that the invoker cannot be reused to
969/// start another method call until a value of this type is dropped and therefore the additional
970/// error information is no longer accessible.
971#[derive(Clone, Copy, Debug, Eq, Hash, PartialEq)]
972pub enum MethodCallError<'invoker> {
973	CborDecode,
974	BufferTooShort,
975	NoSuchComponent,
976	NoSuchMethod,
977	BadParameters(LastException<'invoker>),
978	QueueFull,
979	QueueEmpty,
980	BadDescriptor,
981	TooManyDescriptors,
982	Other(LastException<'invoker>),
983	Unknown,
984}
985
986impl<'invoker> MethodCallError<'invoker> {
987	/// Checks a system call return value of type `isize` for an error value.
988	///
989	/// Returns a `Result` containing a `MethodCallError` if the value is negative, or the
990	/// original value if it was nonnegative.
991	///
992	/// # Errors
993	/// This function fails if the parameter is negative, decoding the represented error code.
994	///
995	/// # Panics
996	/// This function panics if the syscall error code is `MemoryFault` or `StringDecode`. These
997	/// syscall errors should be impossible in safe code because the type system prohibits them:
998	/// `MemoryFault` should be impossible because all memory regions are taken as slices which are
999	/// always valid, and `StringDecode` should be impossible because all strings are taken as
1000	/// string-slices (`&str`) which are always valid UTF-8.
1001	fn from_isize(
1002		_: PhantomData<&'invoker mut Invoker>,
1003		value: isize,
1004	) -> core::result::Result<usize, MethodCallError<'invoker>> {
1005		match value {
1006			-1 => panic_or_trap!("Memory fault"), // Impossible due to memory safety
1007			-2 => Err(Self::CborDecode),
1008			-3 => panic_or_trap!("String decode error"), // Impossible due to type safety of &str
1009			-4 => Err(Self::BufferTooShort),
1010			-5 => Err(Self::NoSuchComponent),
1011			-6 => Err(Self::NoSuchMethod),
1012			-7 => Err(Self::BadParameters(LastException::new(PhantomData))),
1013			-8 => Err(Self::QueueFull),
1014			-9 => Err(Self::QueueEmpty),
1015			-10 => Err(Self::BadDescriptor),
1016			-11 => Err(Self::TooManyDescriptors),
1017			-12 => Err(Self::Other(LastException::new(PhantomData))),
1018			x if x < 0 => Err(Self::Unknown),
1019			_ => {
1020				// Cast from isize to usize is safe because the match arm verifies that x ≥ 0.
1021				#[allow(clippy::cast_sign_loss)]
1022				Ok(value as usize)
1023			}
1024		}
1025	}
1026
1027	/// Returns a string describing the error.
1028	#[must_use = "This function is only useful for its return value"]
1029	pub fn as_str(self) -> &'static str {
1030		self.simplify().as_str()
1031	}
1032
1033	/// Throws away the additional error information.
1034	#[must_use = "This function is only useful for its return value"]
1035	pub fn simplify(self) -> Error {
1036		match self {
1037			Self::CborDecode => Error::CborDecode,
1038			Self::BufferTooShort => Error::BufferTooShort,
1039			Self::NoSuchComponent => Error::NoSuchComponent,
1040			Self::NoSuchMethod => Error::NoSuchMethod,
1041			Self::BadParameters(_) => Error::BadParameters,
1042			Self::QueueFull => Error::QueueFull,
1043			Self::QueueEmpty => Error::QueueEmpty,
1044			Self::BadDescriptor => Error::BadDescriptor,
1045			Self::TooManyDescriptors => Error::TooManyDescriptors,
1046			Self::Other(_) => Error::Other,
1047			Self::Unknown => Error::Unknown,
1048		}
1049	}
1050}
1051
1052impl Display for MethodCallError<'_> {
1053	fn fmt(&self, f: &mut Formatter<'_>) -> core::fmt::Result {
1054		self.simplify().fmt(f)
1055	}
1056}
1057
1058impl From<MethodCallError<'_>> for Error {
1059	fn from(source: MethodCallError<'_>) -> Self {
1060		source.simplify()
1061	}
1062}
1063
1064impl TryFrom<Error> for MethodCallError<'static> {
1065	type Error = ();
1066
1067	fn try_from(source: Error) -> core::result::Result<Self, Self::Error> {
1068		match source {
1069			Error::CborDecode => Ok(Self::CborDecode),
1070			Error::BufferTooShort => Ok(Self::BufferTooShort),
1071			Error::NoSuchComponent => Ok(Self::NoSuchComponent),
1072			Error::NoSuchMethod => Ok(Self::NoSuchMethod),
1073			Error::QueueFull => Ok(Self::QueueFull),
1074			Error::QueueEmpty => Ok(Self::QueueEmpty),
1075			Error::BadDescriptor => Ok(Self::BadDescriptor),
1076			Error::TooManyDescriptors => Ok(Self::TooManyDescriptors),
1077			Error::Unknown => Ok(Self::Unknown),
1078			Error::BadParameters | Error::Other => Err(()),
1079		}
1080	}
1081}
1082
1083#[cfg(feature = "std")]
1084impl std::error::Error for MethodCallError<'_> {}
1085
1086/// The result of a call to [`end_length`](MethodCall::end_length).
1087///
1088/// The `'invoker` lifetime parameter is the lifetime of the method invoker that is performing the
1089/// call.
1090#[derive(Debug, Eq, PartialEq)]
1091pub enum InvokeEndLengthResult<'invoker> {
1092	/// The method call is complete. If the method call completed successfully, the `Result` value
1093	/// contains both the length of the call result, in bytes, and the [`MethodCall`] value that
1094	/// can be used to fetch the result if desired. If the method call failed, the `Result` value
1095	/// contains the error.
1096	Done(core::result::Result<(usize, MethodCall<'invoker>), MethodCallError<'invoker>>),
1097
1098	/// The method call is not finished yet. The [`MethodCall`] value is returned so the caller can
1099	/// continue to monitor progress.
1100	Pending(MethodCall<'invoker>),
1101}
1102
1103/// The result of a call to [`end`](MethodCall::end).
1104///
1105/// The `'invoker` lifetime parameter is the lifetime of the method invoker that is performing the
1106/// call.
1107#[derive(Debug, Eq, PartialEq)]
1108pub enum InvokeEndResult<'invoker> {
1109	/// The method call is complete and the result has been fetched. If the method call completed
1110	/// successfully, the `Result` value contains the CBOR-encoded result. If the method call
1111	/// failed, the `Result` value contains an error.
1112	Done(core::result::Result<usize, MethodCallError<'invoker>>),
1113
1114	/// The method call is complete but the provided buffer was too short to hold the result. The
1115	/// [`MethodCall`] value is returned so the caller can retry with a larger buffer.
1116	BufferTooShort(MethodCall<'invoker>),
1117
1118	/// The method call is not finished yet. The [`MethodCall`] value is returned so the caller can
1119	/// continue to monitor progress.
1120	Pending(MethodCall<'invoker>),
1121}
1122
1123impl<'invoker> InvokeEndResult<'invoker> {
1124	/// Unwraps an `InvokeEndResult`, assuming that the caller already knows that the result is
1125	/// `Done`. This function is useful if the caller knows that the method call is complete and
1126	/// that the buffer is large enough to hold any possible return value, or if the caller is not
1127	/// in a position to handle large return values anyway.
1128	///
1129	/// # Errors
1130	/// * [`BufferTooShort`](MethodCallError::BufferTooShort) is returned if the result was
1131	///   actually `BufferTooShort`.
1132	/// * [`QueueEmpty`](MethodCallError::QueueEmpty) is returned if the result was actually
1133	///   `QueueEmpty`.
1134	///
1135	/// In case of any error, because the [`MethodCall`] is consumed, the method call is cancelled.
1136	#[must_use = "This function is only useful for its return value"]
1137	pub fn expect_done(self) -> core::result::Result<usize, MethodCallError<'invoker>> {
1138		match self {
1139			Self::Done(result) => result,
1140			Self::BufferTooShort(_) => Err(MethodCallError::BufferTooShort),
1141			Self::Pending(_) => Err(MethodCallError::QueueEmpty),
1142		}
1143	}
1144}