use super::error::{Error, Result};
use core::fmt::{Debug, Formatter};
use core::marker::PhantomData;
use core::mem::forget;
use core::num::NonZeroU32;
use minicbor::data::Tag;
use minicbor::decode::{Decode, Decoder};
use minicbor::encode::{Encode, Encoder, Write};
use oc_wasm_sys::descriptor as sys;
const IDENTIFIER: u64 = 39;
fn cbor_encode<W: Write>(
descriptor: u32,
e: &mut Encoder<W>,
) -> core::result::Result<(), minicbor::encode::Error<W::Error>> {
e.tag(Tag::Unassigned(IDENTIFIER))?.u32(descriptor)?;
Ok(())
}
pub trait AsRaw {
#[must_use = "This function is only useful for its return value"]
fn as_raw(&self) -> u32;
}
#[allow(clippy::module_name_repetitions)] pub trait AsDescriptor {
#[must_use = "This function is only useful for its return value"]
fn as_descriptor(&self) -> Borrowed<'_>;
}
#[allow(clippy::module_name_repetitions)] pub trait IntoDescriptor {
#[must_use = "This function is only useful for its return value"]
fn into_descriptor(self) -> Owned;
}
#[derive(Eq, Hash, Ord, PartialEq, PartialOrd)]
pub struct Owned(NonZeroU32);
impl Owned {
#[allow(clippy::must_use_candidate)] pub const unsafe fn new(raw: u32) -> Self {
Self(NonZeroU32::new_unchecked(raw + 1))
}
#[must_use = "The returned descriptor will leak if not manually closed"]
pub const fn into_inner(self) -> u32 {
let ret = self.as_raw();
forget(self);
ret
}
#[must_use = "This function is only useful for its return value"]
pub const fn as_raw(&self) -> u32 {
self.0.get() - 1
}
pub fn dup(&self) -> Result<Self> {
let new_desc = Error::from_i32(unsafe { sys::dup(self.as_raw()) })?;
Ok(unsafe { Self::new(new_desc) })
}
}
impl AsRaw for Owned {
fn as_raw(&self) -> u32 {
self.0.get() - 1
}
}
impl AsDescriptor for Owned {
fn as_descriptor(&self) -> Borrowed<'_> {
Borrowed(self.0, PhantomData)
}
}
impl IntoDescriptor for Owned {
fn into_descriptor(self) -> Owned {
self
}
}
impl Debug for Owned {
fn fmt(&self, f: &mut Formatter<'_>) -> core::fmt::Result {
self.as_raw().fmt(f)
}
}
impl Drop for Owned {
fn drop(&mut self) {
unsafe { sys::close(self.as_raw()) };
}
}
impl<Context> Encode<Context> for Owned {
fn encode<W: Write>(
&self,
e: &mut Encoder<W>,
_: &mut Context,
) -> core::result::Result<(), minicbor::encode::Error<W::Error>> {
cbor_encode(self.as_raw(), e)
}
}
#[derive(Clone, Copy, Eq, Hash, Ord, PartialEq, PartialOrd)]
pub struct Borrowed<'a>(NonZeroU32, PhantomData<&'a NonZeroU32>);
impl Borrowed<'_> {
#[must_use = "This function is only useful for its return value"]
pub const fn as_raw(self) -> u32 {
self.0.get() - 1
}
}
impl AsRaw for Borrowed<'_> {
fn as_raw(&self) -> u32 {
self.0.get() - 1
}
}
impl AsDescriptor for Borrowed<'_> {
fn as_descriptor(&self) -> Borrowed<'_> {
*self
}
}
impl Debug for Borrowed<'_> {
fn fmt(&self, f: &mut Formatter<'_>) -> core::fmt::Result {
self.as_raw().fmt(f)
}
}
impl<Context> Encode<Context> for Borrowed<'_> {
fn encode<W: Write>(
&self,
e: &mut Encoder<W>,
_: &mut Context,
) -> core::result::Result<(), minicbor::encode::Error<W::Error>> {
cbor_encode(self.as_raw(), e)
}
}
#[derive(Eq, Hash, Ord, PartialEq, PartialOrd)]
pub struct Decoded(NonZeroU32);
impl Decoded {
#[allow(clippy::must_use_candidate)] pub unsafe fn into_owned(self) -> Owned {
Owned(self.0)
}
}
impl Debug for Decoded {
fn fmt(&self, f: &mut Formatter<'_>) -> core::fmt::Result {
(self.0.get() - 1).fmt(f)
}
}
impl<'b, Context> Decode<'b, Context> for Decoded {
fn decode(
d: &mut Decoder<'b>,
_: &mut Context,
) -> core::result::Result<Self, minicbor::decode::Error> {
let tag = d.tag()?;
if tag != Tag::Unassigned(IDENTIFIER) {
return Err(minicbor::decode::Error::message("expected Identifier tag"));
}
Ok(Self(NonZeroU32::new(d.u32()? + 1).unwrap()))
}
}