use super::*;
#[derive(Copy, Clone, Debug, Default, Eq, PartialEq, Hash)]
#[repr(transparent)]
pub struct BaseObject {
pub(crate) value: u32,
}
impl BaseObject {
pub const INVALID: BaseObject = BaseObject { value: 0 };
#[inline]
#[track_caller]
pub fn unwrap(self) -> Self {
#[cold]
fn panic_invalid_handle(handle: BaseObject) -> ! {
panic!("Invalid handle: BaseObject({})", handle.value);
}
if matches!(self, Self::INVALID) {
panic_invalid_handle(self);
}
return self;
}
}
macro_rules! define_handle {
($name:ident) => {
#[doc = concat!(stringify!($name), " handle.")]
#[derive(Copy, Clone, Debug, Default, Eq, PartialEq, Hash)]
#[repr(transparent)]
pub struct $name {
pub(crate) value: u32,
}
impl $name {
pub const INVALID: $name = $name { value: 0 };
#[inline]
#[track_caller]
pub fn unwrap(self) -> Self {
#[cold]
fn panic_invalid_handle(handle: $name) -> ! {
panic!(concat!("Invalid handle: ", stringify!($name),"({})"), handle.value);
}
if matches!(self, Self::INVALID) {
panic_invalid_handle(self);
}
return self;
}
#[allow(dead_code)]
#[inline]
pub(crate) fn unwrap_or(self, default: Self) -> Self {
if matches!(self, Self::INVALID) {
return default;
}
return self;
}
}
impl From<$name> for crate::BaseObject {
#[inline]
fn from($name { value }: $name) -> Self {
crate::BaseObject { value }
}
}
};
}
#[derive(Copy, Clone, Debug, Eq, PartialEq)]
pub enum ObjectType {
VertexBuffer,
IndexBuffer,
ShaderProgram,
Texture2D,
}
pub trait ObjectCast<U> {
fn try_cast(self, g: &Graphics) -> Option<U>;
}
impl ObjectCast<BaseObject> for BaseObject {
#[inline]
fn try_cast(self, _g: &Graphics) -> Option<BaseObject> {
Some(self)
}
}
impl ObjectCast<VertexBuffer> for BaseObject {
#[inline]
fn try_cast(self, g: &Graphics) -> Option<VertexBuffer> {
match g.get_type(self)? {
ObjectType::VertexBuffer => Some(VertexBuffer { value: self.value }),
_ => None,
}
}
}
impl ObjectCast<IndexBuffer> for BaseObject {
#[inline]
fn try_cast(self, g: &Graphics) -> Option<IndexBuffer> {
match g.get_type(self)? {
ObjectType::IndexBuffer => Some(IndexBuffer { value: self.value }),
_ => None,
}
}
}
impl ObjectCast<ShaderProgram> for BaseObject {
#[inline]
fn try_cast(self, g: &Graphics) -> Option<ShaderProgram> {
match g.get_type(self)? {
ObjectType::ShaderProgram => Some(ShaderProgram { value: self.value }),
_ => None,
}
}
}
impl ObjectCast<Texture2D> for BaseObject {
#[inline]
fn try_cast(self, g: &Graphics) -> Option<Texture2D> {
match g.get_type(self)? {
ObjectType::Texture2D => Some(Texture2D { value: self.value }),
_ => None,
}
}
}
impl ObjectCast<BaseObject> for VertexBuffer {
#[inline]
fn try_cast(self, _g: &Graphics) -> Option<BaseObject> {
Some(BaseObject { value: self.value })
}
}
impl ObjectCast<BaseObject> for IndexBuffer {
#[inline]
fn try_cast(self, _g: &Graphics) -> Option<BaseObject> {
Some(BaseObject { value: self.value })
}
}
impl ObjectCast<BaseObject> for ShaderProgram {
#[inline]
fn try_cast(self, _g: &Graphics) -> Option<BaseObject> {
Some(BaseObject { value: self.value })
}
}
impl ObjectCast<BaseObject> for Texture2D {
#[inline]
fn try_cast(self, _g: &Graphics) -> Option<BaseObject> {
Some(BaseObject { value: self.value })
}
}
impl ObjectCast<VertexBuffer> for VertexBuffer {
#[inline]
fn try_cast(self, _g: &Graphics) -> Option<VertexBuffer> {
Some(self)
}
}
impl ObjectCast<IndexBuffer> for IndexBuffer {
#[inline]
fn try_cast(self, _g: &Graphics) -> Option<IndexBuffer> {
Some(self)
}
}
impl ObjectCast<ShaderProgram> for ShaderProgram {
#[inline]
fn try_cast(self, _g: &Graphics) -> Option<ShaderProgram> {
Some(self)
}
}
impl ObjectCast<Texture2D> for Texture2D {
#[inline]
fn try_cast(self, _g: &Graphics) -> Option<Texture2D> {
Some(self)
}
}