#[cfg(feature = "bevy_reflect")]
use bevy_reflect::Reflect;
use core::{
marker::PhantomData,
ops::{Deref, DerefMut},
panic::Location,
};
#[cfg_attr(feature = "bevy_reflect", derive(Reflect))]
#[derive(Copy, Clone, Debug, Eq, Hash, Ord, PartialEq, PartialOrd)]
pub struct MaybeLocation<T: ?Sized = &'static Location<'static>> {
#[cfg_attr(feature = "bevy_reflect", reflect(ignore, clone))]
marker: PhantomData<T>,
#[cfg(feature = "track_location")]
value: T,
}
impl<T: core::fmt::Display> core::fmt::Display for MaybeLocation<T> {
fn fmt(&self, _f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {
#[cfg(feature = "track_location")]
{
self.value.fmt(_f)?;
}
Ok(())
}
}
impl<T> MaybeLocation<T> {
#[inline]
pub const fn new(_value: T) -> Self
where
T: Copy,
{
Self {
#[cfg(feature = "track_location")]
value: _value,
marker: PhantomData,
}
}
#[inline]
pub fn new_with(_f: impl FnOnce() -> T) -> Self {
Self {
#[cfg(feature = "track_location")]
value: _f(),
marker: PhantomData,
}
}
#[inline]
pub fn map<U>(self, _f: impl FnOnce(T) -> U) -> MaybeLocation<U> {
MaybeLocation {
#[cfg(feature = "track_location")]
value: _f(self.value),
marker: PhantomData,
}
}
#[inline]
pub fn zip<U>(self, _other: MaybeLocation<U>) -> MaybeLocation<(T, U)> {
MaybeLocation {
#[cfg(feature = "track_location")]
value: (self.value, _other.value),
marker: PhantomData,
}
}
#[inline]
pub fn unwrap_or_default(self) -> T
where
T: Default,
{
self.into_option().unwrap_or_default()
}
#[inline]
pub fn into_option(self) -> Option<T> {
#[cfg(feature = "track_location")]
{
Some(self.value)
}
#[cfg(not(feature = "track_location"))]
{
None
}
}
}
impl<T> MaybeLocation<Option<T>> {
#[inline]
pub fn new_with_flattened(_f: impl FnOnce() -> Option<MaybeLocation<T>>) -> Self {
Self {
#[cfg(feature = "track_location")]
value: _f().map(|value| value.value),
marker: PhantomData,
}
}
#[inline]
pub fn transpose(self) -> Option<MaybeLocation<T>> {
#[cfg(feature = "track_location")]
{
self.value.map(|value| MaybeLocation {
value,
marker: PhantomData,
})
}
#[cfg(not(feature = "track_location"))]
{
Some(MaybeLocation {
marker: PhantomData,
})
}
}
}
impl<T> MaybeLocation<&T> {
#[inline]
pub const fn copied(&self) -> MaybeLocation<T>
where
T: Copy,
{
MaybeLocation {
#[cfg(feature = "track_location")]
value: *self.value,
marker: PhantomData,
}
}
}
impl<T> MaybeLocation<&mut T> {
#[inline]
pub const fn copied(&self) -> MaybeLocation<T>
where
T: Copy,
{
MaybeLocation {
#[cfg(feature = "track_location")]
value: *self.value,
marker: PhantomData,
}
}
#[inline]
pub fn assign(&mut self, _value: MaybeLocation<T>) {
#[cfg(feature = "track_location")]
{
*self.value = _value.value;
}
}
}
impl<T: ?Sized> MaybeLocation<T> {
#[inline]
pub const fn as_ref(&self) -> MaybeLocation<&T> {
MaybeLocation {
#[cfg(feature = "track_location")]
value: &self.value,
marker: PhantomData,
}
}
#[inline]
pub const fn as_mut(&mut self) -> MaybeLocation<&mut T> {
MaybeLocation {
#[cfg(feature = "track_location")]
value: &mut self.value,
marker: PhantomData,
}
}
#[inline]
pub fn as_deref(&self) -> MaybeLocation<&T::Target>
where
T: Deref,
{
MaybeLocation {
#[cfg(feature = "track_location")]
value: &*self.value,
marker: PhantomData,
}
}
#[inline]
pub fn as_deref_mut(&mut self) -> MaybeLocation<&mut T::Target>
where
T: DerefMut,
{
MaybeLocation {
#[cfg(feature = "track_location")]
value: &mut *self.value,
marker: PhantomData,
}
}
}
impl MaybeLocation {
#[inline]
#[track_caller]
pub const fn caller() -> Self {
MaybeLocation {
#[cfg(feature = "track_location")]
value: Location::caller(),
marker: PhantomData,
}
}
}