windows-core 0.100.0

Core type support for COM and Windows
Documentation
use super::*;
use core::mem::transmute;

/// A borrowed ABI-compatible input parameter.
#[repr(transparent)]
pub struct InRef<'a, T: Type<T>>(T::Abi, core::marker::PhantomData<&'a T>);

impl<T: Type<T>> InRef<'_, T> {
    /// Returns `true` if the argument is null.
    pub fn is_null(&self) -> bool {
        T::is_null(&self.0)
    }

    /// Returns the referenced value or `E_POINTER` if null.
    pub fn ok(&self) -> Result<&T> {
        self.as_ref()
            .ok_or_else(|| Error::from_hresult(imp::E_POINTER))
    }

    /// Returns the referenced value if non-null.
    pub fn as_ref(&self) -> Option<&T> {
        if self.is_null() {
            None
        } else {
            unsafe { Some(self.assume_init_ref()) }
        }
    }

    /// Returns the referenced value.
    ///
    /// # Panics
    ///
    /// Panics if the argument is null.
    #[track_caller]
    pub fn unwrap(&self) -> &T {
        self.as_ref()
            .expect("called `InRef::unwrap` on a null value")
    }

    /// Converts the argument to an [`Option<T>`] by cloning the reference.
    pub fn cloned(&self) -> Option<T> {
        self.as_ref().cloned()
    }

    unsafe fn assume_init_ref(&self) -> &T {
        unsafe { T::assume_init_ref(&self.0) }
    }
}

impl<T: Type<T>> Default for InRef<'_, T> {
    fn default() -> Self {
        unsafe { core::mem::zeroed() }
    }
}

impl<T: Type<T>> core::ops::Deref for InRef<'_, T> {
    type Target = T::Default;
    fn deref(&self) -> &Self::Target {
        unsafe { transmute(&self.0) }
    }
}

impl<'a, T: Type<T, InterfaceType>> From<&'a Option<T>> for InRef<'a, T>
where
    T: TypeKind<TypeKind = InterfaceType>,
{
    fn from(from: &'a Option<T>) -> Self {
        unsafe { core::mem::transmute_copy(from) }
    }
}

impl<'a, T: Type<T, InterfaceType>> From<Option<&'a T>> for InRef<'a, T>
where
    T: TypeKind<TypeKind = InterfaceType>,
{
    fn from(from: Option<&'a T>) -> Self {
        if let Some(from) = from {
            unsafe { core::mem::transmute_copy(from) }
        } else {
            unsafe { core::mem::zeroed() }
        }
    }
}

impl<'a, T: Type<T>> From<&'a T> for InRef<'a, T> {
    fn from(from: &'a T) -> Self {
        unsafe { core::mem::transmute_copy(from) }
    }
}