fidl_next/fuchsia/wire/
handle.rsuse core::fmt;
use core::mem::replace;
use crate::zx::sys::{zx_handle_t, ZX_HANDLE_INVALID};
use crate::zx::{Handle, HandleBased as _};
use crate::fuchsia::{HandleDecoder, HandleEncoder};
use crate::{
munge, u32_le, Decode, DecodeError, Encodable, EncodableOption, Encode, EncodeError,
EncodeOption, Slot, TakeFrom,
};
#[repr(C, align(4))]
pub union WireHandle {
encoded: u32_le,
decoded: zx_handle_t,
}
impl Drop for WireHandle {
fn drop(&mut self) {
drop(self.take());
}
}
impl WireHandle {
pub fn set_encoded_present(slot: Slot<'_, Self>) {
munge!(let Self { mut encoded } = slot);
*encoded = u32_le::from_native(u32::MAX);
}
pub fn is_invalid(&self) -> bool {
self.as_raw_handle() == ZX_HANDLE_INVALID
}
pub fn take(&mut self) -> Handle {
let raw = unsafe { replace(&mut self.decoded, ZX_HANDLE_INVALID) };
unsafe { Handle::from_raw(raw) }
}
#[inline]
pub fn as_raw_handle(&self) -> zx_handle_t {
unsafe { self.decoded }
}
}
impl fmt::Debug for WireHandle {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
self.as_raw_handle().fmt(f)
}
}
unsafe impl<D: HandleDecoder + ?Sized> Decode<D> for WireHandle {
fn decode(mut slot: Slot<'_, Self>, decoder: &mut D) -> Result<(), DecodeError> {
munge!(let Self { encoded } = slot.as_mut());
match encoded.to_native() {
0 => (),
u32::MAX => {
let handle = decoder.take_handle()?;
munge!(let Self { mut decoded } = slot);
decoded.write(handle.into_raw());
}
e => return Err(DecodeError::InvalidHandlePresence(e)),
}
Ok(())
}
}
impl TakeFrom<WireHandle> for Handle {
fn take_from(from: &mut WireHandle) -> Self {
from.take()
}
}
#[derive(Debug)]
#[repr(transparent)]
pub struct WireOptionalHandle {
handle: WireHandle,
}
impl WireOptionalHandle {
pub fn set_encoded_present(slot: Slot<'_, Self>) {
munge!(let Self { handle } = slot);
WireHandle::set_encoded_present(handle);
}
pub fn set_encoded_absent(slot: Slot<'_, Self>) {
munge!(let Self { handle: WireHandle { mut encoded } } = slot);
*encoded = u32_le::from_native(ZX_HANDLE_INVALID);
}
pub fn is_some(&self) -> bool {
!self.handle.is_invalid()
}
pub fn is_none(&self) -> bool {
self.handle.is_invalid()
}
pub fn take(&mut self) -> Option<Handle> {
self.is_some().then(|| self.handle.take())
}
#[inline]
pub fn as_raw_handle(&self) -> Option<zx_handle_t> {
self.is_some().then(|| self.handle.as_raw_handle())
}
}
impl Encodable for Handle {
type Encoded<'buf> = WireHandle;
}
impl<E: HandleEncoder + ?Sized> Encode<E> for Handle {
fn encode(
&mut self,
encoder: &mut E,
slot: Slot<'_, Self::Encoded<'_>>,
) -> Result<(), EncodeError> {
if self.is_invalid() {
Err(EncodeError::InvalidRequiredHandle)
} else {
let handle = replace(self, Handle::invalid());
encoder.push_handle(handle)?;
WireHandle::set_encoded_present(slot);
Ok(())
}
}
}
impl EncodableOption for Handle {
type EncodedOption<'buf> = WireOptionalHandle;
}
impl<E: HandleEncoder + ?Sized> EncodeOption<E> for Handle {
fn encode_option(
this: Option<&mut Self>,
encoder: &mut E,
slot: Slot<'_, Self::EncodedOption<'_>>,
) -> Result<(), EncodeError> {
if let Some(handle) = this {
let handle = replace(handle, Handle::invalid());
encoder.push_handle(handle)?;
WireOptionalHandle::set_encoded_present(slot);
} else {
WireOptionalHandle::set_encoded_absent(slot);
}
Ok(())
}
}
impl TakeFrom<WireOptionalHandle> for Option<Handle> {
fn take_from(from: &mut WireOptionalHandle) -> Self {
from.take()
}
}